【问题标题】:Why is React rendering the children in this scenario? (State is the same, using useState)为什么 React 在这种情况下渲染孩子? (状态相同,使用useState)
【发布时间】:2020-10-04 09:01:52
【问题描述】:

Code Sandbox

import React, { useState, useEffect } from "react";

const Foo = () => {
  console.log("render foo");
  return <div> foo</div>;
};

const App = () => {
  const [value, setValue] = useState(1);

  useEffect(() => {
    console.log("effect", value);
  }, [value]);

  console.log("rendering");
  return (
    <div>
      {" "}
      <Foo /> <button onClick={() => setValue(value)}>Click To Render</button>
    </div>
  );
};

export default App;

现在根据React Documentation

如果您将 State Hook 更新为与当前状态相同的值,React 将退出 而不渲染子级或触发效果(强调我的) (React 使用 Object.is 比较算法。)

请注意,React 在退出之前可能仍需要再次渲染该特定组件。这不应该是一个问题,因为 React 不会不必要地“深入”到树中。如果您在渲染时进行昂贵的计算,您可以使用 useMemo 对其进行优化。

在我给出的示例中,我们可以看到 useEffect 挂钩没有触发,如文档所述,但我的 Foo 组件正在渲染。

这是为什么?

我认为内联函数可能会导致渲染 - 但如果我使用 useCallback 将其更改为记忆函数,则会发生相同的行为:

  const handleClick = useCallback(() => setValue(value), [value]);

  console.log("rendering");
  return (
    <div>
      {" "}
      <Foo /> <button onClick={handleClick}>Click To Render</button>
    </div>

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    救援逻辑是在 react-dom 的 v16.8.0 中实现的,其中 react 还引入了钩子,而您的演示使用了 alpha 版本的钩子,这就是为什么即使您更新时仍然会看到重新渲染被触发的原因相同的状态

    根据v16.8.0 发布说明

    • 避免渲染 useState 和 useReducer Hooks 的相同值。 (@acdlite 在#14569)

    【讨论】:

    • 呃。谢谢。很高兴知道要注意这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2018-06-10
    • 2021-06-01
    • 1970-01-01
    • 2017-01-07
    • 2015-05-20
    • 2013-07-22
    相关资源
    最近更新 更多