首页 > 解决方案 > 反应 useCallback 钩子,没有收到更新的依赖状态值

问题描述

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

任何人都知道为什么我的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>

标签: javascriptreactjsreact-hooksdependenciesdom-events

解决方案


handleKeydown函数在每次更改时更新activeTab。但是,仅在挂载时调用useEffect将函数绑定到事件的方法。keydown因此,虽然函数被重新创建,但初始值为 的原始实例activeTab被事件处理程序调用。

这里useCallback是多余的,你也可以使用功能更新的形式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>


推荐阅读