React:如何使用useCallback以避免全量更新?

react 如何使用useCallback 避免全量更新?

在子组件的事件中使用useCallback

fd3e60779771043277351a5329d1868.png

父组件 list.map 创建了子组件, 子组件触发事件导致 父组件的 list 发生变更, 于是组件全部发生了变化
这个过程中只有其中一个子组件发生了改变,所以我使用了 memo 包裹了一下
但是 传递的事件函数会重复创建,导致子组件全量更新
我应该如何使用useCallback 来实现顶点更新?

<SingleCircle
    fill="#fff" name={name} x={x} y={y} radius={4 / scale}
    onDragEnd={() => onDrop(name)}
    onDragMove={(e: TKDragEvent) => onDragMove(e, index)}
    onMouseOver={() => dispatch(setSelectPointKey(name))}

    // 注释这样写会报错
    // onDragEnd={useCallback(() => onDrop(name), [])}
    // onDragMove={useCallback((e: TKDragEvent) => onDragMove(e, index), [index])}
    // onMouseOver={useCallback(() => dispatch(setSelectPointKey(name)), [])}
/>

image.png
image.png

阅读 1.2k
avatarAI BotBETA

要使用 useCallback 来避免不必要的重新渲染,你需要确保回调函数在每次渲染时都保持不变。在你的例子中,你可以使用 useCallback 来创建这些回调函数,并将它们作为 onDragEndonDragMoveonMouseOver 的属性。

首先,你需要创建一个状态变量来存储 onDroponDragMovesetSelectPointKey 函数的引用。然后,在函数体内部,使用 useCallback 钩子来创建一个回调函数,并将其存储在相应的状态变量中。

下面是一个示例代码:

import React, { useState, useCallback } from 'react';

function ParentComponent() {
  const [list, setList] = useState([/* 初始列表 */]);
  const [selectedPointKey, setSelectedPointKey] = useState(null);

  const onDrop = (name) => {
    // 处理 onDrop 逻辑
  };

  const onDragMove = (e, index) => {
    // 处理 onDragMove 逻辑
  };

  const setSelectPointKey = (name) => {
    // 处理 setSelectPointKey 逻辑
  };

  const onDragEndCallback = useCallback(() => onDrop, []); // 创建 onDrop 回调函数
  const onDragMoveCallback = useCallback((e, index) => onDragMove(e, index), [index]); // 创建 onDragMove 回调函数,并依赖 index 防止重新渲染
  const setSelectPointKeyCallback = useCallback(() => setSelectPointKey, []); // 创建 setSelectPointKey 回调函数

  return (
    <div>
      {list.map((item, index) => (
        <SingleCircle
          fill="#fff"
          name={item.name}
          x={item.x}
          y={item.y}
          radius={4 / item.scale}
          onDragEnd={onDragEndCallback} // 使用创建的回调函数作为 onDragEnd 属性
          onDragMove={(e: TKDragEvent) => onDragMoveCallback(e, index)} // 使用创建的回调函数作为 onDragMove 属性,并传递 index 作为参数
          onMouseOver={() => setSelectedPointKey(item.name)} // 根据你的需求修改 onMouseOver 处理函数
        />
      ))}
    </div>
  );
}

这样,只有当 index 值改变时,onDragMove 的回调函数才会改变,从而触发组件的重新渲染。其他情况下,回调函数保持不变,因此不会触发不必要的重新渲染。

1 个回答

useCallback 提到外面去就好了,报错是因为这样写在 map 循环里面
image.png
image.png

当然还可以使用其他方案

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题