极客时间返利平台,你可以在上边通过山月的链接购买课程,并添加我的微信 (shanyue94) 领取返现。
每天晚上九点 B站讲解前端工程化直播,并解答相关问题。

# 当多次重复点击按钮时,以下三个 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 new window)

"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”的参数是字符串,相比对象的比较简单了很多,所以不会导致重新渲染。

Last Updated: 11/27/2021, 10:11:48 AM