React-Redux中Props更新后函数未即时触发状态更新的问题求助
问题:React-Redux Connect传递Props后,子组件状态无法即时更新
我通过react-redux的connect从mapStateToProps获取props,将其传递给子组件。该props作为函数参数,函数返回值作为子组件的状态。我确认props已更新(页面显示正确),但函数未即时更新状态,需切换react-router路由再返回才生效。请问如何实现即时更新?是否做法有误?求指导。
附代码:
import React, { Component } from 'react'; import {connect} from "react-redux"; import filterData from "../../States/AllStates/filterData" import BookComponent from "./BookComponent"; const mapStateToProps = state => { return { fmlProps: state.ReducerName.fmlProps } }; class Testing extends Component { state = { // this.props.fmlPropsdoesn't work right away. You need to go away then come back // to see the desired result, which I want to avoid XXX: filterData(this.props.fmlProps) } render() { return ( <> <h1>{this.props.fmlProps}</h1> {/* this show up correct */} {this.state.XXX.map(FakeData => ( <BookComponent key={FakeData.planNumber} PNum={FakeData.planNumber} PName={FakeData.planName} /> ))} </> ); } } export default connect(mapStateToProps, null) (Testing);
解答
嘿,我来帮你捋清楚问题所在:你现在的写法里,state.XXX只在组件第一次初始化的时候赋值了一次!也就是说,当this.props.fmlProps从Redux store更新时,组件的state并不会自动跟着重新计算——只有当组件被卸载再重新挂载(比如你切换路由再回来)的时候,state才会重新初始化,这就是为什么你要切路由才生效。
下面给你几个解决办法,按推荐程度排序:
方法一:直接在render里计算(最推荐,最简单)
如果filterData这个函数的计算开销不大,完全没必要把结果存在state里。直接在render的时候计算,这样每次props更新,render都会重新执行,结果自然就即时更新了:
class Testing extends Component { render() { // 每次render时根据最新的props计算 const filteredData = filterData(this.props.fmlProps); return ( <> <h1>{this.props.fmlProps}</h1> {filteredData.map(FakeData => ( <BookComponent key={FakeData.planNumber} PNum={FakeData.planNumber} PName={FakeData.planName} /> ))} </> ); } }
这种写法省掉了维护state的麻烦,代码更简洁,还能保证数据始终是最新的。
方法二:用componentDidUpdate监听props变化
如果filterData计算开销比较大,不想每次render都执行,那可以用生命周期钩子监听props变化,只有当fmlProps真的改变时才更新state:
class Testing extends Component { state = { XXX: filterData(this.props.fmlProps) }; // 组件挂载完成后初始化一次(可选,因为state已经初始化了,但如果props在挂载后才更新的话可以加) componentDidMount() { this.setState({ XXX: filterData(this.props.fmlProps) }); } // 当props更新时触发 componentDidUpdate(prevProps) { // 对比前后props,只有变化了才更新state if (prevProps.fmlProps !== this.props.fmlProps) { this.setState({ XXX: filterData(this.props.fmlProps) }); } } render() { return ( <> <h1>{this.props.fmlProps}</h1> {this.state.XXX.map(FakeData => ( <BookComponent key={FakeData.planNumber} PNum={FakeData.planNumber} PName={FakeData.planName} /> ))} </> ); } }
方法三:用getDerivedStateFromProps(复杂场景用)
如果你的组件有更复杂的state和props同步需求,可以用这个静态生命周期方法,它是专门用来处理props到state的同步的:
class Testing extends Component { state = { XXX: filterData(this.props.fmlProps), lastFmlProps: this.props.fmlProps // 存一下当前props,用来对比变化 }; // 静态方法,在render之前触发,用来根据props更新state static getDerivedStateFromProps(nextProps, prevState) { // 如果新的props和之前存的不一样,就返回新的state if (nextProps.fmlProps !== prevState.lastFmlProps) { return { XXX: filterData(nextProps.fmlProps), lastFmlProps: nextProps.fmlProps }; } // 不需要更新state就返回null return null; } render() { return ( <> <h1>{this.props.fmlProps}</h1> {this.state.XXX.map(FakeData => ( <BookComponent key={FakeData.planNumber} PNum={FakeData.planNumber} PName={FakeData.planName} /> ))} </> ); } }
内容的提问来源于stack exchange,提问作者adnan tariq
相关产品推荐
相关产品推荐

