提问者:小点点

为什么要在这个场景中渲染孩子?(状态相同,使用useState)


代码沙箱

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将在不呈现子级或射击效果的情况下退出。(强调我的)(React使用Object.is比较算法。)

请注意,在退出之前,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>

共1个答案

匿名用户

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

根据v16.8.0版本说明

  • 放弃对useState和useReucer钩子的相同值进行渲染。(@acdlite in#14569)