高级前端
react
【Q502】当多次重复点击按钮时,以下三个 Heading 是如何渲染的

当多次重复点击按钮时,以下三个 Heading 是如何渲染的

更多描述

import React, { memo, useMemo, useState } from "react";
 
const Heading = memo(({ style, title }) => {
  console.log("Rendered:", title);
 
  return <h1 style={style}>{title}</h1>;
});
 
export default function App() {
  const [count, setCount] = useState(0);
 
  const normalStyle = {
    backgroundColor: "teal",
    color: "white",
  };
 
  const memoizedStyle = useMemo(() => {
    return {
      backgroundColor: "red",
      color: "white",
    };
  }, []);
 
  return (
    <>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Increment {count}
      </button>
      <Heading style={memoizedStyle} title="Memoized" />
      <Heading style={normalStyle} title="Normal" />
      <Heading title="React.memo Normal" />
    </>
  );
}

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 512 (opens in a new tab)

Author 回答者: buzuosheng (opens in a new tab)

"Memoized"只在第一次渲染时打印一次,后续点击不刷新。 "Normal"会在每次渲染时打印。 "React.memo Normal”只会在第一次渲染时打印一次。

使用useMemo时,依赖数组为null,这意味着只会在首次渲染时,对memoizedStyle进行一次计算,后续不再计算。 在渲染`组件时,React.memo会先判断前后状态

memoizedStyle === memoizedStyle; //true

由于状态始终是一个对象,自身始终是与自身相等的,所以不会导致重新渲染。

没有使用useMemo时,每次点击,对<Heading />组件传入属性,React.memo判断

 {
    backgroundColor: "teal",
    color: "white",
  } ===  {
    backgroundColor: "teal",
    color: "white",
  }  // false

每次都会传入一个新的对象,由于React.memo对prop进行浅比较,两个对象总是不相等的。 如果需要进行深比较,可以对React.memo传入一个深比较函数作为第二个参数。

"React.memo Normal”的参数是字符串,相比对象的比较简单了很多,所以不会导致重新渲染。