要使用 useCallback
来避免不必要的重新渲染,你需要确保回调函数在每次渲染时都保持不变。在你的例子中,你可以使用 useCallback
来创建这些回调函数,并将它们作为 onDragEnd
、onDragMove
和 onMouseOver
的属性。
首先,你需要创建一个状态变量来存储 onDrop
、onDragMove
和 setSelectPointKey
函数的引用。然后,在函数体内部,使用 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
的回调函数才会改变,从而触发组件的重新渲染。其他情况下,回调函数保持不变,因此不会触发不必要的重新渲染。
把


useCallback
提到外面去就好了,报错是因为这样写在map
循环里面当然还可以使用其他方案
ahooks
里面的useMemoizedFn
,是之前React
官方useEvent
提案的实现,函数引用始终不会变,并且不会产生过期闭包,无需依赖项https://ahooks.js.org/zh-CN/hooks/use-memoized-fn