为什么我的组件会使用React.memo重新渲染

3
每次我的选项卡组件父级重新渲染时,我的子组件也会重新渲染。
我的选项卡组件父级如下:
import { useState } from "react";
import "./styles.scss";
import Tab from "./tab";

export default function App() {
  const [selectTab, setSelectTab] = useState("a");
  console.log("parent render");
  return (
    <div className="App">
      <div className="tab-list">
        <Tab tab={"a"} title={"First Title"} setSelectTab={setSelectTab} />
        <Tab tab={"b"} title={"Second Title"} setSelectTab={setSelectTab} />
        <Tab 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>
  );
}

我的选项卡组件代码
const Tab = ({ title, tab, setSelectTab }) => {
  console.log("child render");
  const handleClick = (tab) => {
    setSelectTab(tab);
  }
  return <p onClick={() => handleClick(tab)}>{title}</p>;
};

export default Tab;

每次渲染,我都会打印一次 "parent render" 和三次 "child render"。
当父组件状态改变时,组件属性不会发生变化,因此我认为可以使用 React.memo 跳过组件的重新渲染,并进行了以下更改:
我的父组件:
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>
  );
}

我的记忆化选项卡组件代码

import React, { useCallback } from "react";

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

export default Tab;
export const MemoizedTab = React.memo(Tab);

但是我和我的非缓存代码一样记录控制台日志。是什么导致选项卡组件重新渲染,如何停止不必要的重新渲染?

我怀疑可能是来自父级的setSelectTab函数在每次重新渲染时都是一个新的函数,这导致组件重新渲染,尽管使用了useCallback

Codesandbox链接


我注意到这里不需要使用 useCallback,因为组件没有从父组件接收回调函数。 - dev_el
1个回答

4
以下是导入语句
import MemoizedTab from "./tab";

导入默认导出,而不是命名导出。

记忆化的Tab组件作为命名导出进行导出,而作为默认导出导出的则没有被记忆化。

这就是为什么Tab组件会进行不必要的重新渲染。

将导入语句更改为

import { MemoizedTab } from "./tab";

为了防止Tab组件不必要的重新渲染。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接