【问题标题】:Why does this React setter work if it should be a stale closure?如果这个 React setter 应该是一个陈旧的闭包,为什么它会起作用?
【发布时间】:2023-01-26 13:24:13
【问题描述】:

我有这个下面的功能。我的随机化函数在渲染中是相同的,因为我将它包装在 useCallback 中。当我单击随机化按钮时,它会重新呈现我的应用程序。

然而,当我点击那个按钮时,因为randomize被记忆了,我不使用旧的setNum功能吗?这是如何运作的? setter 函数不是链接到它们各自的状态,所以陈旧的 setter 函数会改变一个过时的状态吗?将 setter 包含在依赖项中是最佳做法吗?由于代码似乎按原样工作,它有什么实际区别?

export default function App() {
  const [num, setNum] = useState(0);

  const randomize = useCallback(() => {
    setNum(Math.random());
  }, []);

  return (
    <div className="App">
      <h4>{num}</h4>
      <button onClick={randomize}>Randomize</button>
    </div>
  );
}

【问题讨论】:

    标签: javascript reactjs usecallback


    【解决方案1】:

    useCallback 中没有引用有状态值,因此不存在可能导致问题的陈旧状态。

    此外,状态设置器是稳定的引用——它在所有渲染中都是完全相同的功能。每个不同的setNum不绑定只要到它自己的渲染 - 你可以随时调用对它的任何引用,然后组件将重新渲染。

    let lastFn;
    const App = () => {
        const [value, setValue] = React.useState(0);
        if (lastFn) {
          console.log('Re-render. Setter is equal to previous setter:', lastFn === setValue);
        }
        lastFn = setValue;
        setTimeout(() => {
          setValue(value + 1);
        }, 1000);
        return (
          <div>
            {value}
          </div>
        );
    };
    
    ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div class='react'></div>

    将 setter 包含在依赖项中是最佳做法吗?

    一般来说,是的,将内部引用的所有内容作为依赖项包含在内是个好主意 - 但 ESLint 的 rules of hooks 足够智能,可以识别 useState 返回的函数是稳定的,因此不需要包含在内在依赖数组中。 (几乎所有来自 props 或 state 的东西应该虽然被包含在依赖数组中,exhaustive-deps 会在缺少某些东西时警告你)

    【讨论】:

      【解决方案2】:

      setter 函数不是链接到它们各自的状态,所以陈旧的 setter 函数会改变过时的状态吗?

      不。

      从文档:钩子 API 参考 > 基本钩子 > useState:

      笔记

      React 保证 setState 函数标识是稳定的并且不会在重新渲染时改变。这就是为什么可以安全地从 useEffectuseCallback 依赖项列表中省略的原因。


      将 setter 包含在依赖项中是最佳做法吗?

      从技术上讲,这是一种反优化潜移默化运行时成本。没关系。如果它让您有信心遵守规则,请添加它。

      【讨论】:

        猜你喜欢
        • 2020-12-20
        • 1970-01-01
        • 2022-01-23
        • 2016-12-22
        • 2013-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-23
        相关资源
        最近更新 更多