react性能优化,memo函数如何保证组件的不必要渲染?
发布于 作者:苏南大叔 来源:程序如此灵动~本文属于react
性能优化的经验文章,意思是:如果不按照本文的写法(添加memo
)去做的话,也没有啥大问题。本文使用的是react
目前推荐的函数式组件的写法,如果您使用的是传统的类式组件,可以使用memo
,但是更加推荐您使用PureComponent
。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述react
高阶组件中的memo
函数,这个函数的作用是:智能判断传入组件的props
是否发生了变化。如果发生了变化,则渲染组件。如果没有发生变化,则不渲染组件。测试环境:create-react-app@5.0.1
,react@18.2.0
,react-dom@18.2.0
,node@16.14.2
。
特别说明
值得特别说明的是:memo
是属于react
的高阶组件,可以用于函数式组件,也可以用于类式组件。memo
实际上还有第二个参数,监控props
的变化,有条件的允许子组件更新。参考文章:
https://newsn.net/say/react-memo-2.html
这里描述的数据变化是有条件的,对于高级类型(比如array
或object
)变量,是有特例的。请参考:
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>
);
父组件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;
子组件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;
其中定义了两个state
普通变量:selfData
和nextData
。
注意:这里就仅仅是普通的数字或字符串变量,不是数组不是对象。
nextData
会作为子组件的props
进行传递,而selfData
不会被传递进入子组件,只在父组件里面使用。相关文章:
父组件里面有两个按钮,分别对应用于修改selfData
和nextData
。
优化之前
在对子组件进行优化之前,对selfData
和nextData
的变量修改,都会引起父组件和子组件的重新渲染(没变化的话,就其实是变量类型的问题,待议)。这里存在问题的地方就是:当对selfData
进行修改的时候,子组件也被重新渲染了,而实际上子组件根本不需要进行渲染,因为它的任何设置都没有变化。
使用memo
进行优化
优化的步骤也非常简单,第一步导入memo
。
import React,{memo} from 'react';
第二步,包裹函数式组件。
export default memo(Child);
可以再次运行查看组件效果,可以看到:对selfData
进行修改的时候,并不会引起子组件的变化了。优化成功!
相关链接
总结
更多react
相关经验文章,请点击:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。