You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中基于useReducer实现点击按钮展示筛选后待办事项状态的技术咨询

实现Todo筛选渲染的思路和代码优化

Hey,我来帮你搞定这个筛选切换的问题!其实核心思路就是用一个状态跟踪当前选中的筛选类型,然后根据这个类型动态渲染对应的待办列表,而且咱们还能优化一下你现在的状态结构,避免冗余~

步骤1:添加筛选状态

首先在组件里加一个状态,用来记录当前用户选择的筛选类型(全部/活跃/已完成):

import { useState, useReducer, useMemo } from 'react';

// ... 其他代码

export default function TodosState() {
  const [todosState, dispatchTodos] = useReducer(todosReducer, todosInitalState);
  // 新增筛选状态,默认显示全部
  const [filter, setFilter] = useState('all');
  
  const uncheckedTodos = todosState.todos.filter(todo => !todo.completed);
  
  // ... 其他代码
}

步骤2:给筛选按钮绑定状态更新事件

给三个筛选按钮加上点击事件,点击时更新filter状态,还可以给选中的按钮加个高亮样式提升体验:

<div className={styles.buttons}>
  <button 
    onClick={() => setFilter('all')}
    className={filter === 'all' ? styles.active : ''}
  >
    All
  </button>
  <button 
    onClick={() => setFilter('active')}
    className={filter === 'active' ? styles.active : ''}
  >
    Active
  </button>
  <button 
    onClick={() => setFilter('completed')}
    className={filter === 'completed' ? styles.active : ''}
  >
    Completed
  </button>
</div>

(styles.active是可选的自定义样式类,你可以根据自己的CSS需求调整高亮效果)

步骤3:根据筛选状态动态计算要渲染的列表

你原来的状态里维护了activeTodos和completedTodos,其实完全可以不用存这两个数组——每次根据主todos数组和当前filter动态过滤就行,这样能避免状态同步的麻烦(比如修改todo的completed状态时,不用同时更新三个数组)。

用useMemo做缓存,避免每次渲染都重复过滤:

// 根据筛选状态动态计算要显示的todo列表
const filteredTodos = useMemo(() => {
  switch(filter) {
    case 'active':
      return todosState.todos.filter(todo => !todo.completed);
    case 'completed':
      return todosState.todos.filter(todo => todo.completed);
    default: // 'all'
      return todosState.todos;
  }
}, [filter, todosState.todos]); // 依赖项变化时才重新计算

步骤4:渲染过滤后的列表

把原来渲染todosState.todos的地方换成filteredTodos就行:

<ul>
  {filteredTodos.map((todo) => {
    return (
      <TodoItem 
        key={todo.id} 
        id={todo.id} 
        text={todo.todoValue} 
        onCheck={saveCheckedValues} 
      ></TodoItem>
    );
  })}
</ul>

额外优化:简化初始状态

既然不再需要维护activeTodos和completedTodos,可以把初始状态简化成只保留主todos数组:

const todosInitalState = {
  todos: [
    {todoValue: "exampleTodo", id: 3.14, completed: false},
    {todoValue: "exampleTodoNo2", id: 42, completed: true}
  ]
};

这样你的reducer逻辑也能更简洁,不用处理三个数组的同步啦~

这样一来,点击不同的筛选按钮,就会自动切换渲染对应状态的待办事项了!

内容的提问来源于stack exchange,提问作者Ayhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 15:57:47