React中props为何仅在render函数生效,componentDidMount中无效?
问题根源
过滤逻辑本身没有错误,问题出在React类组件生命周期执行时机和异步数据的时序差:
componentDidMount仅在组件首次挂载完成后执行一次。这个执行节点上,你拿到的this.props.catalog、this.props.currentMarket还是父组件传入的初始值(通常是空数组/undefined,因为绝大多数场景下catalog是父组件通过接口异步拉取的,首次挂载时请求还没返回),此时执行过滤逻辑得到的自然是空数组,setState写入的filtered也就是空值。- 后续父组件拿到接口返回的完整数据,会通过props更新传入子组件,触发子组件重新执行
render函数,这时候render里拿到的是更新后的完整props,所以过滤结果正确,但componentDidMount不会在组件更新阶段重复触发,自然不会重新执行过滤逻辑更新state。
修复方法
两种常用方案,优先选第一种:
- 方案1(推荐):不需要把过滤结果存在state中,直接在render阶段做派生计算
这种方式没有状态同步成本,每次props更新触发render时都会自动用最新值计算,不会出现时序问题:render() { const filteredList = this.props.catalog.filter(word => word.markets.some(m => m === this.props.currentMarket) ) return ( <div> <div className="ui divider"></div> {/* 直接使用filteredList渲染即可 */} </div> ) } - 方案2:如果业务场景必须要把过滤结果存在state中,使用
componentDidUpdate监听props变化,在props更新时重新计算
注意必须加前后props的对比判断,否则会触发「setState→render→componentDidUpdate→setState」的死循环:componentDidUpdate(prevProps) { // 只有参与计算的props发生变化时才重新计算 if ( prevProps.catalog !== this.props.catalog || prevProps.currentMarket !== this.props.currentMarket ) { const filteredList = this.props.catalog.filter(word => word.markets.some(m => m === this.props.currentMarket) ) this.setState({ filtered: filteredList }) } }
内容的提问来源于stack exchange,提问作者Chen
相关产品推荐
相关产品推荐

