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

本文描述react项目中的高阶函数memo,前面的文章里面,苏南大叔对这个memo已经做过简单的描述了,最基本的印象就是用于监控组件的props的变化情况,如果props没有变化,就不更新组件。这个组件可以是函数式组件,也可以是类式组件。

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - react-memo-2
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-1)

苏南大叔的程序如此灵动博客,记录苏南大叔的代码感想。本文描述react高阶组件memo的高级使用方式:有条件的允许更新。测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@16.14.2

前置内容

本文的前置内容是下面的这篇文章:

本文的例子,和上文的例子非常类似。但是,本文中使用类式组件【以及函数式组件】来做子组件的例子,然后使用高阶函数memo来做这个有条件的缓存。

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - 执行截图
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-2)

父组件

import './App.css';
import React, { useState, memo, Component } from 'react';

function App() {
  const [selfData, setSelfData] = useState(0) // 不传入子组件
  const [nextData, setNextData] = useState(1) // 传入子组件
  return (
    <div className="App">
      <table>
        <tbody>
          <tr>
            <td>
              <button onClick={() => setSelfData((val) => val + 1)}>selfData,不应该引起子组件渲染,但是引起了</button>
            </td>
            <td>{selfData}</td>
          </tr>
          <tr>
            <td>
              <button onClick={() => setNextData((val) => val + 1)}>nextData,应该引起子组件渲染,5之后不渲染</button>
            </td>
            <td>{nextData}</td>
          </tr>
        </tbody>
      </table>
      <Child nextData={nextData} />
      <Child2 nextData={nextData} />
    </div>
  );
}
export default App;

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - 父组件代码
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-3)

函数式组件memo

// import React,{memo} from 'react';
const Child_ = (props) => {
  const { nextData } = props
  return (
    <>
      {
        console.log('函数组件渲染了!!!', Date.now().toString().slice(-6))
      }
      <table>
        <tbody>
          <tr>
            <td>函数组件nextData</td>
            <td>{nextData}</td>
          </tr>
          <tr>
            <td>函数组件被渲染时间</td>
            <td>{Date.now().toString().slice(-6)}</td>
          </tr>
        </tbody>
      </table>
    </>
  )
}
const Child = memo(Child_, (prev, next) => {
  console.log(prev, next);
  if (prev.nextData < 5) return false; //允许更新
  return true; //不允许更新
})

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - code-1
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-4)

类式组件memo

// import React,{memo} from 'react';
class Child2_ extends Component {
  constructor(props) {
    super(props)
  }
  componentDidUpdate() {
    console.log('类式组件渲染了!!!', Date.now().toString().slice(-6))
  }
  render() {
    return (<table>
      <tbody>
        <tr>
          <td>类式组件nextData</td>
          <td>{this.props.nextData}</td>
        </tr>
        <tr>
          <td>类式组件被渲染时间</td>
          <td>{Date.now().toString().slice(-6)}</td>
        </tr>
      </tbody>
    </table>)
  }
}
const Child2 = memo(Child2_, (prev, next) => {
  console.log(prev, next);
  if (prev.nextData < 5) return false; //允许更新
  return true; //不允许更新
})

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - code-2
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-5)

执行效果

本文执行效果如下:
父组件中,有两个按钮,第一个按钮总是会引起子组件更新。第二个按钮在计数到5之前会引起两个子组件的更新。

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - 运行结果2
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-6)

第二个参数 对比 shouldComponentUpdate

memo的第二个参数是个回调函数:

(prev, next) => {
  console.log(prev, next);
  //return false; //允许更新
  return true;    //不允许更新
}

这个看起来和shouldComponentUpdate很类似,可以回顾一下shouldComponentUpdate的用法:

shouldComponentUpdate(nextProps, nextState) {
  console.log('shouldComponentUpdate');
  console.log(nextProps, nextState);
  // return false;
  return true;
}

苏南大叔:react教程,memo高阶函数的高级使用方法,有条件的更新 - 数值变化监控
react教程,memo高阶函数的高级使用方法,有条件的更新(图7-7)

可见两者区别是:

函数辨别标准return truereturn false
memo(,(prev, next)=>{})前后props不允许更新允许更新
shouldComponentUpdate(nextProps, nextState)下一个propsstate允许更新不允许更新

总结

memo虽然客观上是要保持缓存组件的,但是组件的缓存条件也可以是有条件的。特别需要注意的是:这里的truefalse表达的意思,和shouldComponentUpdate()是相反的!!!

更多react经验文章,请点击苏南大叔的博客:

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

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

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

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