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

本文属于react性能优化的经验文章,意思是:如果不按照本文的写法(添加memo)去做的话,也没有啥大问题。本文使用的是react目前推荐的函数式组件的写法,如果您使用的是传统的类式组件,可以使用memo,但是更加推荐您使用PureComponent

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - memo保证组件不必要渲染
react性能优化,memo函数如何保证组件的不必要渲染?(图7-1)

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述react高阶组件中的memo函数,这个函数的作用是:智能判断传入组件的props是否发生了变化。如果发生了变化,则渲染组件。如果没有发生变化,则不渲染组件。测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@16.14.2

特别说明

值得特别说明的是:memo是属于react的高阶组件,可以用于函数式组件,也可以用于类式组件。
memo实际上还有第二个参数,监控props的变化,有条件的允许子组件更新。参考文章:
https://newsn.net/say/react-memo-2.html

这里描述的数据变化是有条件的,对于高级类型(比如arrayobject)变量,是有特例的。请参考:
https://newsn.net/say/react-issue-state-object.html

测试例子

本文中苏南大叔使用的例子,来自create-react-app的默认模版cra-template。参考文章:

由于React.StrictMode严格模式的原因,默认情况下,所有组件都会被渲染两次。所以,测试本例的时候,建议注释掉React.StrictMode严格模式。参考文章:

对这个例子进行一些改造,本文主要的需求内容是:保证子组件不被多次不必要的渲染。所以,这里新建了一个Child.js函数式组件,用于接收父组件传递的props

index.js代码:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  // <React.StrictMode>
    <App />
  // </React.StrictMode>
);

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - 禁用严格模式
react性能优化,memo函数如何保证组件的不必要渲染?(图7-2)

父组件App.js代码:

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

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,应该引起子组件渲染</button>
            </td>
            <td>{nextData}</td>
          </tr>
        </tbody>
      </table>
      <Child nextData={nextData}></Child>
    </div>
  );
}
export default App;

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - app父组件
react性能优化,memo函数如何保证组件的不必要渲染?(图7-3)

子组件Child.js代码:

// import React,{memo} from 'react';
const Child = (props) => {
  const { nextData } = props
  return (
    <>
      {
      console.log('组件渲染了!!!',Date.now())
      }
      <table>
        <tbody>
        <tr>
          <td>子组件拿到的nextData</td>
          <td>{nextData}</td>
        </tr>
        <tr>
          <td>子组件被渲染的时间</td>
          <td>{Date.now()}</td>
        </tr>
        </tbody>
      </table>
    </>
  )
}
// export default memo(Child);
export default Child;

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - 子组件
react性能优化,memo函数如何保证组件的不必要渲染?(图7-4)

其中定义了两个state普通变量:selfDatanextData

注意:这里就仅仅是普通的数字或字符串变量,不是数组不是对象。

nextData会作为子组件的props进行传递,而selfData不会被传递进入子组件,只在父组件里面使用。相关文章:

父组件里面有两个按钮,分别对应用于修改selfDatanextData

优化之前

在对子组件进行优化之前,对selfDatanextData的变量修改,都会引起父组件和子组件的重新渲染(没变化的话,就其实是变量类型的问题,待议)。这里存在问题的地方就是:当对selfData进行修改的时候,子组件也被重新渲染了,而实际上子组件根本不需要进行渲染,因为它的任何设置都没有变化。

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - 子组件被重新渲染了
react性能优化,memo函数如何保证组件的不必要渲染?(图7-5)

使用memo进行优化

优化的步骤也非常简单,第一步导入memo

import React,{memo} from 'react';

第二步,包裹函数式组件。

export default memo(Child);

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - 引入memo
react性能优化,memo函数如何保证组件的不必要渲染?(图7-6)

可以再次运行查看组件效果,可以看到:对selfData进行修改的时候,并不会引起子组件的变化了。优化成功!

苏南大叔:react性能优化,memo函数如何保证组件的不必要渲染? - 仅仅被引起一次的组件渲染
react性能优化,memo函数如何保证组件的不必要渲染?(图7-7)

相关链接

总结

更多react相关经验文章,请点击:

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

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

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

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