React组件通过Redux Store设置本地状态及问题排查
嘿,我来帮你理清楚这个问题~你遇到的核心问题其实是异步请求的时序问题,咱们一步步拆解:
为什么componentDidMount里直接setState会报错?
你在componentDidMount里调用getArticleDetails后,这个API请求是异步执行的——也就是说,当你紧接着写this.setState({str:this.props.article.title})时,Redux还没完成数据的获取、状态更新以及组件props的传递,此时this.props.article还是undefined,自然会抛出错误。
正确的解决方式
下面给你两种常用且靠谱的方案,你可以根据自己的习惯选择:
方案1:使用componentDidUpdate(推荐,逻辑更直观)
componentDidUpdate会在组件更新(包括props发生变化)后触发,我们可以在这里添加条件判断,只有当props.article从undefined变为有效数据,或者数据发生变化时,才去更新组件的本地状态:
componentDidUpdate(prevProps) { // 关键:必须判断props的变化,避免无限循环 if (this.props.article && this.props.article !== prevProps.article) { this.setState({ str: this.props.article.title }); } }
⚠️ 一定要加上this.props.article !== prevProps.article的判断!如果不加,每次setState都会触发组件重新渲染,进而再次调用componentDidUpdate,形成无限循环。
方案2:使用getDerivedStateFromProps(React官方推荐的替代旧生命周期的方案)
这是一个静态方法,专门用于根据props的变化来更新组件状态,它不能访问this,需要通过参数对比新旧props和状态来返回新的状态:
static getDerivedStateFromProps(nextProps, prevState) { // 当新的article存在,且其title和当前状态的str不同时,返回新状态 if (nextProps.article && nextProps.article.title !== prevState.str) { return { str: nextProps.article.title }; } // 不需要更新状态时返回null return null; }
额外优化建议:是否真的需要本地状态?
你可以思考一下:编辑框的内容是否一定要存到组件本地状态里?其实可以简化逻辑:直接用props.article.title作为编辑框的初始值,在onChange时再维护本地状态,这样就不需要在生命周期里额外处理状态同步了:
render() { return ( <Fragment> {this.props.article === undefined ? ( <Spin /> ) : ( <div style={{ marginRight: '500px' }}> <Paragraph editable={{ onChange: this.onChange }} defaultValue={this.props.article.title} > {this.state.str || this.props.article.title} </Paragraph> </div> )} </Fragment> ) }
最后调整你的初始代码
记得把componentDidMount里多余的setState删掉,只保留触发API请求的代码即可:
componentDidMount(){ this.props.getArticleDetails(this.articleID); // 仅保留这一行 }
这样调整后,就能正常把Redux Store中的article值同步到组件本地状态啦~
内容的提问来源于stack exchange,提问作者Ginger Bread

