React.memo

前言

什么是react的memo,简单来说就是父组件改变时,子组件也会跟着重新渲染(子组件没有用父组件改变了的值),这时我们就要利用memo规避一些无用的页面渲染。

我们可以通过三种方式规避一些无用的渲染:

  1. 类组件的两种方式:
    shouldComponentUpdate
    PureComponnet
  2. 函数组件的一种方式:
    memo

memo(Component, arePropsEqual?)
参数
Component:要进行记忆化的组件。memo
不会修改该组件,而是返回一个新的、记忆化的组件。它接受任何有效的 React 组件,包括函数组件和 forwardRef 组件。

可选参数 arePropsEqual:一个函数,接受两个参数:组件的前一个 props 和新的 props。如果旧的和新的 props相等,即组件使用新的 props 渲染的输出和表现与旧的 props 完全相同,则它应该返回 true。否则返回 false。通常情况下,你不需要指定此函数。默认情况下,React 将使用 Object.is 比较每个 prop。

用法

React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useStateuseContext 的 Hook,当 context 发生变化时,它仍会重新渲染。

默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

当 props 没有改变时跳过重新渲染

在此示例中,请注意 Greeting 组件在 name 更改时重新渲染(因为那是它的 props 之一),但是在 address 更改时不会重新渲染(因为它不作为 props 传递给 Greeting

import { memo, useState } from 'react';

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>
      <label>
        Name{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Address{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
  );
}

const Greeting = memo(function Greeting({ name }) {
  console.log("Greeting was rendered at", new Date().toLocaleTimeString());
  return <h3>Hello{name && ', '}{name}!</h3>;
});

最小化 props 的变化

当你使用 memo 时,只要任何一个 prop 与先前的值不是 浅层相等 的话,你的组件就会重新渲染。这意味着 React 会使用 Object.is 比较组件中的每个 prop 与其先前的值。注意,Object.is(3, 3) 为 true,但 Object.is({}, {}) 为 false。

为了最大化使用 memo 的效果,应该尽量减少 props 的变化次数。例如,如果 props 是一个对象,可以使用 useMemo 避免父组件每次都重新创建该对象:

function Page() {
  const [name, setName] = useState('Taylor');
  const [age, setAge] = useState(42);

  const person = useMemo(
    () => ({ name, age }),
    [name, age]
  );

  return <Profile person={person} />;
}

const Profile = memo(function Profile({ person }) {
  // ...
});

指定自定义比较函数

在极少数情况下,最小化 memoized 组件的 props 更改可能是不可行的。在这种情况下,你可以提供一个自定义比较函数,React 将使用它来比较旧的和新的 props,而不是使用浅比较。这个函数作为 memo 的第二个参数传递。它应该仅在新的 props 与旧的 props 具有相同的输出时返回 true;否则应该返回 false

function Child({value}){
    console.log('I am rendering');
    return (
        <div>{value}</div>
    )
};

function areEqual(prevProps, nextProps) {
    if(prevProps.value===nextProps.value){
        return true
    }else {
        return false
    }
}
export default React.memo(Child,areEqual)

总结

  1. memo会检测props到改变来决定组件是否需要进行重新渲染,换言之就是,被memo函数包起来的组件只有本身的props被改变之后才会重新渲染
  2. memo只能进行浅比较来校验决定是否触发重新渲染。
  3. 即使使用 memo,React组件自己的 state 或正在使用的 context 发生更改,组件也会重新渲染。
  4. memo需要选择那些经常被重新渲染的组件有选择性的去缓存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哚啦A孟

谢谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值