javascript - React useCallback 钩子(Hook),未接收更新的依赖状态值

标签 javascript reactjs react-hooks dependencies dom-events

下面是我试图解决的问题的简化版本。

有人知道为什么我的 handleKeydown 方法没有收到更新的 activeTab 状态变量吗?我认为因为我添加了 activeTab 作为依赖项,所以回调将始终收到更新的值。然而,事实似乎并非如此。

按预期,每次按下按键时都会调用回调;但是,activeTab 始终为 null,即初始值。如有任何帮助,我们将不胜感激!

(我包含了一个代码片段和一个 jsfiddle 链接(因为该片段由于某种原因似乎没有渲染。jsfiddle 至少渲染了哈哈)。)

https://jsfiddle.net/Tom904/98veow5b/4/

const Tabs = () => {
  const [activeTab, setActiveTab] = React.useState(null);
  
  
  const handleKeydown = React.useCallback(event => {
    console.log(activeTab);
    // if a user hits the escape key while a tab is active...
    if (event.key === 'Escape' && activeTab) {
      setActiveTab(null);
    }
  }, [activeTab]);

  React.useEffect(() => {
    window.addEventListener('keydown', handleKeydown);
    return () => {
      window.removeEventListener('keydown', handleKeydown);
    };
  }, []);
  
  return (
    <div>
      <button onClick={() => setActiveTab('1')}>
         1
      </button>
      <button onClick={() => setActiveTab('2')}>
         2
      </button>
      <button onClick={() => setActiveTab('3')}>
         3
      </button>
      <div>
        Active tab: {activeTab || 'None'}
      </div>
    </div>
  )
  
}

ReactDOM.render(
  <Tabs/>,
  document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

最佳答案

handleKeydown 函数会在 activeTab 的每次更改时更新。但是,将函数绑定(bind)到 keydown 事件的 useEffect 仅在挂载时调用。因此,尽管重新创建了该函数,但事件处理程序仍会调用初始值为 activeTab 的原始实例。

这里的useCallback是多余的,也可以使用functional updates useState 形式以避免 activeTab 依赖:

const Tabs = () => {
  const [activeTab, setActiveTab] = React.useState(null);

  React.useEffect(() => {
    const handleKeydown = event => {      
      setActiveTab(activeTab => event.key === 'Escape' && activeTab ? null : activeTab);
    };
  
    window.addEventListener('keydown', handleKeydown);
    return () => {
      window.removeEventListener('keydown', handleKeydown);
    };
  }, []);
  
  return (
    <div>
      <button onClick={() => setActiveTab('1')}>
         1
      </button>
      <button onClick={() => setActiveTab('2')}>
         2
      </button>
      <button onClick={() => setActiveTab('3')}>
         3
      </button>
      <div>
        Active tab: {activeTab || 'None'}
      </div>
    </div>
  )
  
}

ReactDOM.render(
  <Tabs/>,
  document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

关于javascript - React useCallback 钩子(Hook),未接收更新的依赖状态值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66658603/

相关文章:

javascript - 日期天数间隔不应超过 20 天

javascript - 使用javascript匹配字符串中数组的元素之一

javascript - 以编程方式在音频元素上设置当前时间属性会导致事件监听器无限期触发

javascript - 如何有条件地计算 React Native 中的某个状态?

reactjs - 如何确保组件内的常量仅在 React (Native) 中使用钩子(Hook)启动时计算一次?

JavaScript 正则表达式拆分以&符号分隔的字符串

reactjs - 在 React 中,ref 是引用虚拟 DOM 还是实际 DOM?

javascript - 如何更新 reducer 中对象的 1 个属性?

reactjs - React 的 useMemo 方法导致无效的 hook 调用

reactjs - 通过 React useEffect Hook 更新状态时防止无限循环