我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

React里面比较高阶的使用方式:memo()函数是本文的主要内容。memouseMemo()看起来很相似,使用上却有很大的区别。useMemo()作用在函数之上,是对昂贵运算逻辑函数结果的缓存,只能在函数式组件里面使用。memo作用在组件之上,是对组件的缓存,函数式组件类组件,都是其作用对象。

苏南大叔:React缓存,探讨memo函数如何缓存阻止(子)组件渲染? - react-memo
React缓存,探讨memo函数如何缓存阻止(子)组件渲染?(图2-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0create-react-app@5.0.1react-router-dom@6.27.0react@18.3.1

memo高阶函数

memo()直接套用在组件上,无关组件的写法是函数式写法,还是类写法,都可以使用memo()高阶函数。它对组件为目标进行缓存,根据props决定是否执行渲染。主打的就是(子)组件无渲染无变化。

  • 默认情况下,如果传入组件的所有属性,都保持一致。那么,这个组件就没有渲染的必要性。
  • 当然,也可以自定义函数来对前后的属性进行对比。来自行决定是否渲染。return false渲染,true不渲染。
  • 其中特殊的地方就是传入属性是函数定义的时候,表面上是同样的函数,但是如果内存地址不一样的话。也是会被判定为非相同的值的。会被执行渲染。【待续】

测试代码

在下面的测试代码中,一共有五个子组件Child被加载。其中四个被memo高阶函数所包裹。每个子组件里面都输出了数字时间戳,父组件刷新的时候,如果这些数字时间戳没有变化,那么就证明对应的子组件被缓存了,并没有发生再次渲染。

import React, { useState } from "react";
function Child() {
  console.log("child render");
  return <>{Date.now().toString().slice(-6)}</>;
}
const MemoChild = React.memo(Child);
const MemoChild2 = React.memo(Child, (prev, next) => {
  if (next.point > 110) {
    return false;
  }
  return true;
});
export default function App() {
  console.log("parent render");
  const [info, setInfo] = useState({
    name: "sunan大叔",
    point: 100,
  });
  // const setInfo2 =()=>{}
  function setInfo2() {}
  return (
    <div>
      <div>
        【{info.name}】, 中奖率:{info.point}%
        <button
          onClick={() => {
            setInfo({ ...info, point: info.point + 1 });
          }}
        >
          幸运得分
        </button>
      </div>
      <div>
        <table>
          <tbody>
            <tr>
              <td>【组件1】</td>
              <td>
                <Child></Child>
              </td>
              <td>恒定渲染, 父变子就变</td>
            </tr>
            <tr>
              <td>【组件2】</td>
              <td>
                <MemoChild fn={setInfo2}></MemoChild>
              </td>
              <td>恒定渲染, memo, 父组件每次都渲染, 该函数属性随父组件渲染重新定义</td>
            </tr>
            <tr>
              <td>【组件3】</td>
              <td>
                <MemoChild2 point={info.point}></MemoChild2>
              </td>
              <td>有条件渲染, memo, 自定义规则渲染, 先不变(false)后变(true)</td>
            </tr>
            <tr>
              <td>【组件4】</td>
              <td>
                <MemoChild></MemoChild>
              </td>
              <td>恒定不渲染, memo, 无属性无规则, 默认被Memo</td>
            </tr>
            <tr>
              <td>【组件5】</td>
              <td>
                <MemoChild fn={setInfo}></MemoChild>
              </td>
              <td>恒定不渲染, memo, setInfo是useState的导出函数, 不变</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  );
}

苏南大叔:React缓存,探讨memo函数如何缓存阻止(子)组件渲染? - memo缓存与渲染
React缓存,探讨memo函数如何缓存阻止(子)组件渲染?(图2-2)

表格总结

父组件重新渲染的时候,子组件也会即将触发渲染。但是,memo高阶函数,给其包裹的子组件一次选择的机会。如果变化前后的各个属性props没有发生变化,则拒绝渲染。当然,这个规则也可以自定义,根据需要来决定是否渲染。其中,有个容易踩坑的地方,就是如果传入props的属性是个函数的时候,这个函数可能是每次都重新生成的。这个时候,子组件会被渲染。

序号子组件是否Memoprops属性是否渲染
1<Child />恒定渲染
2<MemoChild fn={fn} />fn是个变化的函数恒定渲染
3<MemoChild2 point={p} />point是个变化的数字有条件渲染
4<MemoChild />无任何属性恒定不渲染
5<MemoChild fn={fn2} />fn不变是个useState导出恒定不渲染

相关文章

memo函数的相关文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react