1.问题
最近在做一个内容比较多的页面,在log中发现View会莫名的render很多次,所以稍微看了一下怎么处理无用渲染的情况,做到局部渲染。
举个很简单的栗子:
1.定义两个state,用于存储两个变量
2.定义两个点击事件,用于改变两个变量的值
3.定义一个控件,用于展示两个变量的值
主要是说明两个独立的变量,被一个控件引用,其中一个值的变化,同样会影响到另一个值。
说的不太清除,直接看代码吧
import React, {useMemo, useState} from 'react';
import {Pressable, View, Text} from 'react-native';
export default App;
function App() {
//红绿两个变量
const [redValue, setRedValue] = useState('red ready');
const [greenValue, setGreenValue] = useState('green ready');
return (
<View style={{flex: 1}}>
{/* 点击事件1 */}
<Pressable
onPress={() => {
setRedValue(new Date().getTime());
}}>
<Text style={{padding: 20, backgroundColor: 'red'}}>红色</Text>
</Pressable>
{/* 点击事件2 */}
<Pressable
onPress={() => {
setGreenValue(new Date().getTime() + '被绿');
}}>
<Text style={{padding: 20, backgroundColor: 'green'}}>绿色</Text>
</Pressable>
<PoliceLog top={redValue} bottom={greenValue} />
</View>
);
}
//展示两个变量的控件
function PoliceLog({top, bottom}) {
function changeTopValue(top) {
console.log('Top is Changed.');
return top + ', Tooooop';
}
const newTop = changeTopValue(top);
return (
<>
<Text style={{padding: 20, color: '#2aa4dc'}}>{newTop}</Text>
<Text style={{padding: 20, color: '#1e1e1e'}}>{bottom}</Text>
</>
);
}
分别点击两个Pressable,在界面上看到,PoliceLog对应的值会分别改变,感觉没有问题。 在Log中可以看到,即使top的值没有改变,changeTopValue依然会被调用到。
其实这就是我们经常用到的问题,View莫名的就会render。
由于一开始学习RN使用的是函数式的组件,在研究局部更新等问题给出的结果都是shouldCompnentUpdate,这就很尴尬了,function形式没有这个生命周期了,如果不去处理的话,会造成多次无用渲染的情况。
这时候就是需要useMemo来解决了。
2.解决
在控件中使用useMemo,在第二个参数中指定要处理的参数,当参数匹配成功后,方法才会执行。
代码中修改一行即可
const newTop = useMemo(() => {
changeTopValue(top);
}, [top]);
点击事件后,只有top改变时才能触发changeTopValue事件。
3.总结
useMemo类似模拟了组件式的shouldCompnentUpdate方法,主要用来解决无用渲染的问题,有需要的可以深入学习一下。