Zustand更新单个任务项性能卡顿,如何优化实现流畅内联编辑?
问题描述
我需要渲染数十乃至数千个Task行,这些行中的字段始终处于可编辑状态。每个行包含多个带有onChange事件的字段,用于更新传入的value。当前使用Zustand管理状态,但更新操作速度极慢,几乎无法使用,希望找到更优实现方式以获得流畅的内联编辑体验。
当前Zustand Store代码
import { create } from "zustand"; import { immer } from "zustand/middleware/immer"; import { Task } from "./types"; interface WorkspaceState { tasks: Record<string, Task>; setTasks: (tasks: Record<string, Task>) => void; updateTask: (task: Task) => void; updateTaskOnChange: <K extends keyof Task>( taskId: number, key: K, value: Task[K] ) => void; resetAll: VoidFunction; } const initialState = { tasks: {}, }; export const useWorkspaceState = create<WorkspaceState>()( immer((set) => ({ ...initialState, setTasks: (tasks) => set({ tasks }), updateTask: (updatedTask) => { set((state) => { state.tasks[updatedTask.id] = updatedTask; }); }, updateTaskOnChange: (taskId, key, value) => { set((state) => { const task = state.tasks[taskId]; if (task) { task[key] = value; } }); }, resetAll: () => { set(() => initialState); }, })) );
优化方案
1. 精准订阅状态,减少不必要重渲染
- 每个Task行组件仅订阅自身对应的单条Task数据,而非整个
tasks对象:import { useStore } from "zustand"; import { useWorkspaceState } from "./store"; const TaskRow = ({ taskId }) => { const task = useStore(useWorkspaceState, (state) => state.tasks[taskId], shallow); // 组件逻辑 }; - 用
React.memo包裹Task行组件,确保只有当对应Task数据变化时才重渲染:import { memo } from "react"; const TaskRow = memo(({ taskId }) => { // 组件逻辑 });
2. 优化状态更新逻辑
- 若坚持使用Immer,确保仅修改目标Task的指定字段,避免隐性遍历开销;也可改用原生不可变更新提升性能:
updateTaskOnChange: (taskId, key, value) => { set((state) => ({ tasks: { ...state.tasks, [taskId]: { ...state.tasks[taskId], [key]: value } } })); },
3. 输入事件防抖处理
- 对文本输入类字段添加防抖,避免每一次按键都触发状态更新:
import { useCallback } from "react"; import debounce from "lodash.debounce"; const TaskRow = memo(({ taskId }) => { const updateTaskOnChange = useWorkspaceState((state) => state.updateTaskOnChange); const debouncedUpdate = useCallback( debounce((key, value) => updateTaskOnChange(taskId, key, value), 100), [taskId, updateTaskOnChange] ); const handleChange = (e) => { debouncedUpdate(e.target.name, e.target.value); }; // 渲染输入框 });
4. 虚拟滚动优化DOM数量
- 当Task数量达数千级时,使用虚拟滚动库(如
react-window)仅渲染可视区域内的行,大幅降低DOM节点数量:import { FixedSizeList } from "react-window"; const TaskList = () => { const tasks = useStore(useWorkspaceState, (state) => Object.values(state.tasks), shallow); return ( <FixedSizeList height={600} itemCount={tasks.length} itemSize={50} > {({ index, style }) => ( <div style={style}> <TaskRow taskId={tasks[index].id} /> </div> )} </FixedSizeList> ); };
内容的提问来源于stack exchange,提问作者lkp
相关产品推荐
相关产品推荐

