为啥自定义钩子的回调永远看不到组件道具

Posted

技术标签:

【中文标题】为啥自定义钩子的回调永远看不到组件道具【英文标题】:why callback from custom hook never see component props为什么自定义钩子的回调永远看不到组件道具 【发布时间】:2021-06-01 11:24:23 【问题描述】:

我找不到如何解决一个问题,谁能帮忙

为捕获快捷方式编写了简单的钩子,但来自该自定义钩子的回调在组件中没有看到新的道具

export const useShortcut = (key, isAlt = false, callback) => 
  function onKeyPressed(event) 
    if (event.key.toLowerCase() === key && event.altKey === isAlt) 
      callback();
    
  

  useEffect(() => 
    window.addEventListener("keydown", onKeyPressed);
    return () => 
      window.removeEventListener("keydown", onKeyPressed);
    ;
  , []);
;

export const MyComponent = (props) => 
  function handleShortcut() 
    if (props.prop1) 
      //???prop1 came from parent and components tab tell me but from shortcut hook it always null
    
  

  useShortcuts("n", true, () => handleShortcut());

  return <div></div>;
;

提前多谢

【问题讨论】:

【参考方案1】:
useEffect(() => 
  window.addEventListener("keydown", onKeyPressed);
  return () => 
    window.removeEventListener("keydown", onKeyPressed);
  ;
, []);

由于依赖数组为空,您只需设置一次侦听器,使用第一次渲染中存在的任何onKeyPressed。该函数在第一次渲染时关闭 props,并且永远不会更新。

最简单的解决方法就是移除依赖数组,这样效果每次都会运行:

useEffect(() => 
  window.addEventListener("keydown", onKeyPressed);
  return () => 
    window.removeEventListener("keydown", onKeyPressed);
  ;
);

现在,当组件渲染时,它将拆除旧的侦听器并使用onKeyPressed 的新副本创建一个新侦听器。该新功能会看到新的props


假设,如果设置和拆除侦听器是一项昂贵的操作(事实并非如此),那么您可以通过将 onKeyPressed 放入依赖数组中,将其限制为仅在 onKeyPressed 更改时发生。但是,这需要同时使用useCallback 以确保onKeyPressed 不会更改,除非需要。

useEffect(() => 
  window.addEventListener("keydown", onKeyPressed);
  return () => 
    window.removeEventListener("keydown", onKeyPressed);
  ;
, [onKeyPressed]);

// used like:
export const MyComponent = (props) => 
  const handleShortcut = useCallback(function () 
    if (props.prop1) 
      // ...
    
  , [props.prop1]);

  useShortcuts("n", true, handleShortcut);

【讨论】:

以上是关于为啥自定义钩子的回调永远看不到组件道具的主要内容,如果未能解决你的问题,请参考以下文章

测试自定义钩子:不变违规:找不到 react-redux 上下文值;请确保组件包装在 <Provider>

传递给子组件时道具未定义(反应钩子)

在组件内部定义自定义挂钩是不是有任何问题?

为啥我不能将其转换为自定义的 React 钩子?

如何使用 Apollo 更改道具上的查询?

反应钩子:新状态值未反映在 setInterval 回调中