RN组件状态变化时的重渲染机制及Redux局部状态更新的组件重渲染疑问
React Native组件重渲染与Redux状态关联解析
一、RN组件触发重渲染的常见场景
RN组件的重渲染通常由以下几种情况触发:
- 组件自身的
state通过setState更新 - 父组件传递的
props发生变化(默认通过浅比较判断) - 组件依赖的Context上下文值发生变化
- 调用
forceUpdate强制触发(不推荐使用)
二、Redux场景下的具体问题分析
先明确给定的Redux全局状态:
const data = { a: { value: 1, id: 1 }, b: { value: 2, id: 2 } };
ComponentA依赖data.a,ComponentB依赖data.b。修改data.b时,ComponentA是否重渲染,核心取决于组件从Redux提取状态的方式以及是否做了性能优化。
1. 未做性能优化的情况
如果ComponentA是通过以下方式连接Redux:
- 使用
connect时,mapStateToProps直接返回data.a对象:const mapStateToProps = (state) => ({ a: state.data.a }); - 使用
useSelector时直接返回data.a,且未指定比较函数:const a = useSelector(state => state.data.a);
由于Redux要求状态不可变,修改data.b时会生成一个全新的data对象(data.a的内容没变,但引用地址更新了)。此时:
connect默认对mapStateToProps返回的对象做浅比较,发现a的引用变了,会触发ComponentA重渲染useSelector默认用严格相等(===)判断,同样会因为a的引用变化触发重渲染
2. 做了性能优化的情况
通过以下手段可以避免ComponentA的不必要重渲染:
精准提取状态字段:在
mapStateToProps或useSelector中只提取组件需要的具体属性,而非整个对象:// mapStateToProps写法 const mapStateToProps = (state) => ({ aValue: state.data.a.value, aId: state.data.a.id }); // useSelector写法 const { aValue, aId } = useSelector(state => ({ aValue: state.data.a.value, aId: state.data.a.id }));修改
data.b时,aValue和aId的值未变,组件不会重渲染。使用浅比较函数:配合
useSelector的第二个参数shallowEqual,对比对象的属性值而非引用:import { shallowEqual, useSelector } from 'react-redux'; const a = useSelector(state => state.data.a, shallowEqual);浅比较会检查
a的每个属性值是否变化,只要内容没变,就不会触发重渲染。用React.memo包裹函数组件:如果ComponentA是函数组件,用
React.memo缓存组件,只有当传入的props实际变化时才重渲染:const ComponentA = React.memo(({ a }) => { // 组件渲染逻辑 });结合前面的状态提取优化,就能保证ComponentA仅在
data.a的实际值变化时才重渲染。
总结
默认未做优化时,修改data.b会导致ComponentA重渲染;但通过精准提取状态、使用浅比较或组件缓存等优化手段,可以让ComponentA只在data.a的实际值发生变化时才触发重渲染。
内容的提问来源于stack exchange,提问作者MinisX
相关产品推荐
相关产品推荐

