在componentWillReceiveProps中使用Recompose HOC更新本地状态遇异常
解决Recompose lifecycle HOC同步props到本地状态的坑
嘿,我之前用Recompose的时候也踩过一模一样的坑!要么状态纹丝不动,要么直接栈溢出,简直头大。来给你拆解下问题根源和解决办法:
为什么会出现这两种问题?
- 状态永久固定:大概率是你只在初始化时把props同步到了状态,但没监听后续的props变化;或者判断props是否更新的条件写死了(比如用了错误的相等判断)。
- 栈溢出:这是因为你在
componentWillReceiveProps里直接调用setState,却没加任何条件判断——setState会触发组件重渲染,重渲染又会触发componentWillReceiveProps,无限循环直接把栈撑爆。
正确的实现方式
方式1:用componentWillReceiveProps(兼容旧版本)
核心就是加条件判断,只有当目标props确实和当前值不同时,才更新状态:
import { lifecycle, withState, compose } from 'recompose'; const enhance = compose( // 初始化状态:把props的initialValue赋值给本地状态value withState('value', 'setValue', props => props.initialValue), lifecycle({ componentWillReceiveProps(nextProps) { // 关键:对比新旧props,只有变化了才更新状态 if (nextProps.initialValue !== this.props.initialValue) { this.props.setValue(nextProps.initialValue); } } }) ); const MyComponent = enhance(({ value, setValue }) => ( <input value={value} onChange={(e) => setValue(e.target.value)} placeholder="输入内容" /> ));
方式2:用getDerivedStateFromProps(React推荐的新写法)
componentWillReceiveProps已经被标记为过时了,React更推荐用静态的getDerivedStateFromProps,Recompose的lifecycle HOC也支持这个:
const enhance = compose( withState('value', 'setValue', props => props.initialValue), lifecycle({ static getDerivedStateFromProps(nextProps, prevState) { // 对比新props和当前状态,决定是否更新 if (nextProps.initialValue !== prevState.value) { // 返回新的状态对象,不需要调用setValue return { value: nextProps.initialValue }; } // 返回null表示不更新状态 return null; } }) );
额外注意:引用类型的props对比
如果你的props是对象、数组这种引用类型,直接用!==判断会失效(因为引用不同但内容可能相同)。这时候需要做深比较:
比如用lodash的isEqual:
import _ from 'lodash'; // 在componentWillReceiveProps里: if (!_.isEqual(nextProps.userInfo, this.props.userInfo)) { this.props.setValue(nextProps.userInfo); }
或者自己写针对性的比较逻辑(比如对比对象的关键属性):
static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.user.id !== prevState.user.id) { return { user: nextProps.user }; } return null; }
总结下核心要点
- 永远不要在没有条件判断的情况下同步props到状态——这是栈溢出的元凶
- 对于引用类型,一定要对比内容而不是引用地址
- 优先使用
getDerivedStateFromProps,更符合React的现代规范
内容的提问来源于stack exchange,提问作者Anton Krivokhizhin
相关产品推荐
相关产品推荐

