React中基于状态返回组件时props传递失败的问题及修复建议
我来帮你拆解这个问题的核心原因,再给你最贴合React设计思路的修复方案~
问题根源:你把「组件实例」存进了state里
你现在的写法是在调用showFeatures()/showColors()时,立刻创建了一个组件实例,然后把这个实例存在this.state.showComponent中。这个实例的props是当时调用时this.props的“快照”——之后哪怕父组件更新了resetFeatures这类props,state里的旧组件实例不会自动同步新的props,因为它已经被“固定”下来了,不会重新执行showFeatures()去获取最新的props。
而直接在render()里写<FeaturesList ... />时,每次组件触发render(比如父组件props变化、自身state变化),都会重新生成这个组件实例,自然能拿到最新的this.props值,所以props传递完全正常。
修复方案(推荐第一种,最符合React设计逻辑)
方案1:state存「组件标识」,而非组件实例
不要把组件实例存在state里,而是存一个简单的标识(比如字符串),然后在render()里根据标识动态渲染组件,这样每次render都会用最新的props生成组件:
- 先修改constructor的初始state:
constructor(props) { super(props); this.state = { currentComponent: 'features' }; // 存标识,不是组件实例 this.showFeatures = this.showFeatures.bind(this); this.showColors = this.showColors.bind(this); }
- 简化
showComponentToRender,只更新标识:
showComponentToRender(name) { this.setState({ currentComponent: name }); }
- 在
render()里根据标识动态渲染组件:
render() { let componentToShow; switch(this.state.currentComponent) { case 'features': componentToShow = <FeaturesList updateCad={this.props.updateCad} resetFeatures={this.props.resetFeatures} />; break; case 'colors': componentToShow = <ColorsList switchColor={this.props.switchColor} />; break; default: componentToShow = null; } return ( <div id="features-menu-wrapper"> <nav id="features-menu"> <li onClick={() => this.showComponentToRender('features')}>FEATURES</li> <li onClick={() => this.showComponentToRender('colors')}>COLORS</li> <li onClick={() => this.props.resetCrossbow()}>RESET A4</li> </nav> <div id="component-wrapper"> {componentToShow} </div> </div> ); }
这样修改后,每次render都会根据当前的currentComponent标识,用最新的this.props生成对应的组件,props自然就能正常传递了。
方案2:监听props变化手动更新组件(不推荐)
如果你一定要把组件存在state里,可以在componentDidUpdate生命周期里监听resetFeatures等props的变化,当props更新时重新生成组件并更新state:
componentDidUpdate(prevProps) { // 当resetFeatures或updateCad变化时,如果当前显示的是features组件,重新生成实例 if (prevProps.resetFeatures !== this.props.resetFeatures || prevProps.updateCad !== this.props.updateCad) { if (this.state.currentComponent === 'features') { this.setState({ showComponent: this.showFeatures() }); } } // 同理监听colors相关的props变化 }
但这种方式会增加代码复杂度,而且违背了React“数据驱动视图”的设计理念,所以更推荐方案1。
内容的提问来源于stack exchange,提问作者Joe C

