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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:05:19