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
相关产品推荐
相关产品推荐

