当第二次单击时状态没有改变时组件重新渲染

dev*_*_el 6 javascript reactjs react-hooks

我有一个选项卡组件,每次单击不同的选项卡时都会更改状态。

组件父级

import { useState } from "react";
import "./styles.scss";
import MemoizedTab from "./tab";

export default function App() {
  const [selectTab, setSelectTab] = useState("a");
  console.log("parent render");
  return (
    <div className="App">
      <div className="tab-list">
        <MemoizedTab
          tab={"a"}
          title={"First Title"}
          setSelectTab={setSelectTab}
        />
        <MemoizedTab
          tab={"b"}
          title={"Second Title"}
          setSelectTab={setSelectTab}
        />
        <MemoizedTab
          tab={"c"}
          title={"Third Title"}
          setSelectTab={setSelectTab}
        />
      </div>
      {selectTab === "a" && <div>this is a</div>}
      {selectTab === "b" && <div>this is b</div>}
      {selectTab === "c" && <div>this is c</div>}
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

子组件

import { memo } from "react";

const MemoizedTab = memo(({ title, tab, setSelectTab }) => {
  console.log("child render");
  const handleClick = (tab) => {
    setSelectTab(tab);
  };
  return <p onClick={() => handleClick(tab)}>{title}</p>;
});

export default MemoizedTab;
Run Code Online (Sandbox Code Playgroud)

在初始渲染之后,父级的状态为"a". 当我点击再次"First Title"设置状态"a"时,没有任何内容按预期呈现。

当我第一次单击"Second Title"将状态设置为 的 时"b",我得到了 的控制台日志"parent renders",正如预期的那样。但是当我"Second Title"第二次点击时,"parent renders"即使状态没有改变,我也会再次收到控制台日志。第三次或第四次点击没有任何记录。它总是第二个。

当我单击"Third Title"将状态设置为"c".

为什么我的父级在状态转换后第二次点击时重新渲染?

代码沙盒链接

Jua*_*her 4

React 实际上并没有重新渲染你的组件。您可以通过将 console.log 移动到 componentDidUpdate 挂钩内来验证这一点。

\n
useEffect(()=>{\n   console.log(\'Parent re-rendered!\')\n})\n
Run Code Online (Sandbox Code Playgroud)\n

当您第二次单击任何选项卡时,不会记录此 console.log。

\n

虽然您提供的示例中的 console.log 确实被打印,但 React 最终摆脱了状态更新。这实际上是 React 中的预期行为。以下摘录来自文档

\n
\n

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

\n

请注意,React 可能仍需要在退出之前再次渲染该特定组件。这不应该成为一个问题,因为 React 不会不必要地将 \xe2\x80\x9cdeeper\xe2\x80\x9d 放入树中。

\n
\n