如何将props中的函数加入useCallback依赖数组并避免重复渲染?
组件内部解决onClose导致回调重复创建的方案
方案一:用useRef缓存最新的onClose引用
核心思路是用useRef存储onClose的最新值,让事件回调始终能调用到最新的onClose,同时避免把onClose直接放进useCallback的依赖数组。
代码修改如下:
const Button: React.FC<ButtonProps> = ({ onClose, ...props }) => { // 创建ref存储最新的onClose const onCloseRef = React.useRef(onClose); // 监听onClose变化,更新ref.current React.useEffect(() => { onCloseRef.current = onClose; }, [onClose]); // 用useCallback包裹,依赖只加onCloseRef(ref本身是稳定引用,不会触发重创建) const onKeyDown = React.useCallback((event: KeyboardEvent) => { if (event.keyCode === 65) { // 调用ref里的最新onClose onCloseRef.current(event); } }, [onCloseRef]); React.useEffect(() => { window.addEventListener('keydown', onKeyDown); return () => { window.removeEventListener('keydown', onKeyDown); }; }, [onKeyDown]); // ... 其他组件逻辑 };
这样不管父组件传入的onClose怎么变,onKeyDown只会在组件初始化时创建一次,同时每次触发按键事件时都能拿到最新的onClose。
方案二:直接在useEffect内定义事件回调
如果不想额外用useRef,可以把onKeyDown直接定义在useEffect内部,这样依赖数组只需要加onClose,每次onClose变化时会重新绑定事件,但好处是不用额外处理useCallback的依赖问题。
代码示例:
const Button: React.FC<ButtonProps> = ({ onClose, ...props }) => { React.useEffect(() => { const onKeyDown = (event: KeyboardEvent) => { if (event.keyCode === 65) { onClose(event); } }; window.addEventListener('keydown', onKeyDown); return () => { window.removeEventListener('keydown', onKeyDown); }; }, [onClose]); // 依赖onClose,变化时重新绑定 // ... 其他组件逻辑 };
这个方案的代价是每次onClose变化时,会先解绑旧的事件监听,再绑定新的。如果onClose频繁变化,会有少量的性能开销,但对于大多数场景来说完全可以接受。
方案三:使用useEvent(React 18+ 实验特性)
如果你用的是React 18及以上版本,可以尝试实验性的useEvent钩子,它专门用来处理这种“依赖外部props,但希望回调保持稳定”的场景。
代码示例:
// 注意:useEvent是实验特性,需要开启相关配置 const Button: React.FC<ButtonProps> = ({ onClose, ...props }) => { const onKeyDown = React.useEvent((event: KeyboardEvent) => { if (event.keyCode === 65) { onClose(event); } }); React.useEffect(() => { window.addEventListener('keydown', onKeyDown); return () => { window.removeEventListener('keydown', onKeyDown); }; }, [onKeyDown]); // ... 其他组件逻辑 };
useEvent返回的回调会始终保持引用稳定,同时内部能访问到最新的props和state,不需要手动处理依赖数组。不过因为是实验特性,正式项目使用前要谨慎评估。
内容的提问来源于stack exchange,提问作者Lori
相关产品推荐
相关产品推荐

