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

React Hooks实现shift+click多选任务时如何避免所有TaskItem重渲染

React Hooks shift+click批量选中任务性能优化方案

多选效果演示

问题核心

原有实现将selectedTaskIds加入useCallback依赖,导致每次选中任务后selectTask函数引用更新,所有TaskItem因props变化触发全量重渲染。

优化方案

  • 利用useState函数式更新特性,在更新回调中获取最新的selectedTaskIds值,无需将其加入useCallback依赖
  • 用React.memo包装TaskItem组件,仅当自身props变化时才触发重渲染
  • 可选:若tasks数组会频繁变更,可通过useRef存储tasks的最新引用,进一步移除useCallback对tasks的依赖

优化后代码

父组件逻辑

const [selectedTaskIds, setSelectedTaskIds] = useState<string[]>([])
// 可选:如果tasks会频繁变化,加这个ref存最新tasks,可移除useCallback对tasks的依赖
const tasksRef = useRef(tasks)
useEffect(() => {
  tasksRef.current = tasks
}, [tasks])

const selectTask = useCallback(
  (e: MouseEvent<HTMLDivElement>, taskId: string): void => {
    e.stopPropagation()
    // 用setState函数式更新获取最新的选中列表
    setSelectedTaskIds(prevSelected => {
      const previousTaskId = prevSelected[prevSelected.length - 1]
      if (previousTaskId && e.shiftKey) {
        // 用了tasksRef的话这里替换为tasksRef.current即可
        const previousIdx = tasks.findIndex((task) => task.id === previousTaskId)
        const selectedIdx = tasks.findIndex((task) => task.id === taskId)
        const rangeTasks =
          previousIdx < selectedIdx
            ? tasks.slice(previousIdx, selectedIdx + 1)
            : tasks.slice(selectedIdx, previousIdx + 1)
        const rangeIds = rangeTasks.map((task) => task.id)
        return [...new Set([...prevSelected, ...rangeIds])]
      } else {
        return [taskId]
      }
    })
  },
  [tasks] // 用tasksRef的话这里依赖数组填空即可
)

return (
  {tasks.map((task) => (
    <TaskItem
      key={task.id}
      taskId={task.id}
      onClick={selectTask}
      active={selectedTaskIds.includes(task.id)}
    />
  ))}
)

TaskItem组件包装

// 用React.memo做浅比较,只有props变化时才会触发重渲染
const TaskItem = React.memo(({ taskId, onClick, active }) => {
  // 原有组件逻辑不变
})

优化效果说明

  • selectTask函数引用仅会在tasks变更时更新(用ref存储tasks的话全程引用不变),不会随选中操作频繁变化
  • 每个TaskItem仅当自身active状态变化时才会触发重渲染,不会出现全量重渲染问题
  • 原有shift+click批量选中的功能逻辑完全不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:15:01