涉及到的优化方式
为什么我们需要去优化React组件?,React在组件的渲染上会有什么问题?
- React组件有个特性,在不进行优化处理时父组件更新的时,子组件一定会重新渲染
优化的角度
- 减少组件的不必要渲染
- 提高组件的可读性以及减少复杂度,避免出现难以发现的bug
组件层面的优化
React.memo
memo允许你的组件在 props 没有改变的情况下跳过重新渲染。
使用 memo 将组件包装起来,以获得该组件的一个 记忆化 版本。通常情况下,只要该组件的 props 没有改变,这个记忆化版本就不会在其父组件重新渲染时重新渲染。
这我来解释下
- 组件的数据来源一般情况下有两种
state和props - 在函数组件中
state是做优化的,如果更新的state数据通过对比,未发生改变,组件就不会重新渲染 props函数组件本身是没有做任何处理的,只要props更新了,那组件必更新
上代码
import { useState } from "react";
function Com1(props: any) {
const [com1Data, setCom1Data] = useState(0);
console.log("Com1===> 重新渲染了");
return (
<>
<span>Com1的数据: {com1Data}</span>
<br />
<br />
<button
onClick={() => {
setCom1Data(com1Data + 1);
}}
>
点击更改Com1数据
</button>
<br />
</>
);
}
function Com2(props: any) {
const [com2Data, setCom2Data] = useState(0);
console.log("Com2===> 重新渲染了");
return (
<>
<span>Com2的数据: {com2Data}</span>
<span>父组件的数据: {props.data}</span>
<br />
<br />
<button
onClick={() => {
setCom2Data(com2Data + 1);
}}
>
点击Com2数据
</button>
</>
);
}
function App() {
const [appData, setAppData] = useState(0);
console.log("App===> 重新渲染了");
return (
<div className="App">
<button
onClick={() => {
setAppData(appData + 1);
}}
>
点击更改app数据
</button>
<br />
<br />
<Com1 />
<br />
<Com2 data={appData} />
</div>
);
}
定义了三个组件具有嵌套结构
- 点击Com1按钮
- 点击Com2按钮
- 点击app按钮
重点来了😶🌫️😶🌫️😶🌫️😶🌫️
可以发现Com1组件重新渲染了这就是问题所在,也是没有必要的渲染,这个时候React.Memo就该出手了
function Com1(props: any) {
const [com1Data, setCom1Data] = useState(0);
console.log("Com1===> 重新渲染了");
return (
<>
<span>Com1的数据: {com1Data}</span>
{/* <span>父组件的数据: {props.data}</span> */}
<br />
<br />
<button
onClick={() => {
setCom1Data(com1Data + 1);
}}
>
点击更改Com1数据
</button>
<br />
</>
);
}
// 小小的改动大大的变化🎈🎈🎈
export default React.Memo(Com1)
- 点击App按钮
发现没Com1并没有重新渲染 至于App 和Com2 它们的重新渲染时必须的因为自变量发生了变化
如果用React.memo包裹Com2呢?
function Com2(props: any) {
const [com2Data, setCom2Data] = useState(0);
console.log("Com2===> 重新渲染了");
return (
<>
<span>Com2的数据: {com2Data}</span>
<span>父组件的数据: {props.data}</span>
<br />
<br />
<button
onClick={() => {
setCom2Data(com2Data + 1);
}}
>
点击Com2数据
</button>
</>
);
}
// 这里变了呦🎈🎈🎈🎈🎈
expost default React.Memo(Com2)
function App() {
const [appData, setAppData] = useState(0);
// 这里变了呦🎈🎈🎈🎈🎈
const [appData1, setAppData1] = useState(0);
console.log("App===> 重新渲染了");
return (
<div className="App">
<button
onClick={() => {
setAppData(appData);
}}
>
点击更改appData数据
</button>
// 这里变了呦🎈🎈🎈🎈🎈
<button
onClick={() => {
setAppData1(appData1 + 1);
}}
>
点击更改appData1数据
</button>
<br />
<br />
<Com1 />
<br />
<Com2 data={appData} />
</div>
);
}
- 点击更改appData数据
发现没Com2并没有重新渲染: 因为它所依赖的props数据没有发生变化
- 点击更改appData1数据
发现没有任何组件重新渲染 Why???? :在App组件中state是做优化的,如果更新的state数据通过对比,发现数据没变,所以App组件也没有渲染。
那如果传入的props是引用数据类型呢?
React.memo()的表现是怎么样的?
- 如果是引用类型在在对比数据时:是对比引用地址的,所以在设置引用类型的数据时,建议还是赋值一个新的地址,以免设置后无法更新视图
- 如果依赖的props中有函数,怎样固定函数地址,因为在每次渲染时都会生成不同地址的函数??这就是
useCallback()的需要做的事情了
Memo的其他细节,可以在官网中查看到
下次分享下关于useCallback和 useMemo😁😁😁😁😁😁😁😁😁😁