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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:15:50