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

React TypeScript中如何为复选框值使用useMemo?

React + TypeScript 待办列表功能优化问题

我用React和TypeScript开发了一个待办列表项目,已经实现了新增、删除待办项的功能。每个待办项带有布尔值状态的复选框,希望点击复选框时将该项标记为“已完成”。页面设有Done按钮(对应DoneTasks组件),点击后切换到类主页面的视图,要求已勾选的待办项仅在此页面显示,同时默认主页面要过滤掉已完成的项。我觉得应该用useMemo来处理复选框相关的值,但不确定该放在哪里?


相关代码片段

待办项接口

interface ToDo {
  title: string;
  priority: 1 | 2;
  description: string;
  checked: boolean;
}

待办项组件(带复选框)

function ToDoItem(props: {
  onCheckBoxCheck: (checked: boolean) => void;
  toDo: ToDo;
  onDeleteToDo: () => void;
}) {
  const checkBoxCheck = (event: React.ChangeEvent<HTMLInputElement>) => {
    const isChecked = event.currentTarget.checked;
    props.onCheckBoxCheck(isChecked);
  };

  return (
    <div
      className="to-do-item"
      data-priority={props.toDo.priority}
      id="to-do-item"
    >
      <div className="checkbox-title-container">
        <div className="check-title-div">
          <div>
            <input
              type="checkbox"
              id="checkbox"
              onChange={checkBoxCheck}
              checked={props.toDo.checked}
            />
          </div>
        </div>
      </div>
      {/* 省略删除按钮等其他DOM结构 */}
    </div>
  );
}

const initialTodosString = localStorage.getItem("toDoList");
const initialTodos = initialTodosString
  ? JSON.parse(initialTodosString)
  : [myToDo1, myToDo2]; // myToDo1、myToDo2为预定义的初始待办项

App主组件核心逻辑

function App(): JSX.Element {
  const [toDos, setToDos] = useState<ToDo[]>(initialTodos);
  const [addingToDo, setAddingToDo] = useState(false);
  const [showingDoneTasks, setShowDoneTasks] = useState(false);

  // 疑问:是否要在这里添加useMemo处理checked值?

  useEffect(() => {
    localStorage.setItem("toDoList", JSON.stringify(toDos));
  }, [toDos]);

  function showDone() {
    setShowDoneTasks(true);
  }

  const DoneTasks = () => (
    <div className="App">
      <div className="status-container">
        <button className="activeButton">Active</button>
        <button className="doneButton" onClick={showDone}>Done</button>
      </div>
       {/* 需渲染已完成待办项 */}
    </div>
  );

  if (showingDoneTasks) {
    return <DoneTasks />;
  }

  return (
    <div className="App">
      <div className="status-container">
        <button className="activeButton">Active</button>
        <button className="doneButton" onClick={showDone}>Done</button>
      </div>
      {toDos.map((toDoItem: ToDo) => (
        <ToDoItem
          onDeleteToDo={() => {
            const updatedToDos = toDos.filter((x) => x !== toDoItem);
            setToDos(updatedToDos);
          }}
          onCheckBoxCheck={(checked: boolean) => {
            const updatedToDos = toDos.map((x) =>
              x === toDoItem ? ({ ...x, checked } as any) : x,
            );
            setToDos(updatedToDos);
          }}
          toDo={toDoItem}
        />
      ))}
    </div>
  );
}

解决方案

1. useMemo的正确使用位置

你不需要用useMemo处理复选框的状态值——复选框的状态已经存在toDos数组的每个项中。useMemo的作用是缓存计算结果,避免每次渲染重复执行耗时操作,这里刚好可以用它缓存过滤后的待办项列表:

// 在App组件的hooks区域添加以下代码
const filteredActiveTodos = useMemo(() => {
  return toDos.filter(todo => !todo.checked);
}, [toDos]);

const filteredDoneTodos = useMemo(() => {
  return toDos.filter(todo => todo.checked);
}, [toDos]);

这样每次toDos更新时,只会重新计算一次过滤结果,避免重复执行filter操作。

2. 修复视图切换与渲染问题

  • 给DoneTasks组件的Active按钮添加返回主页面的逻辑:onClick={() => setShowDoneTasks(false)}
  • 渲染待办项时必须添加key属性(建议用唯一标识,比如todo.title或自定义id),React需要它跟踪列表项变化
  • 移除onCheckBoxCheck回调里的as any,利用TypeScript的类型推导即可

3. 最终渲染逻辑调整

  • 主页面渲染filteredActiveTodos(未完成的待办项)
  • DoneTasks组件渲染filteredDoneTodos(已完成的待办项)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:18:01