React组件渲染时向Redux Action传plateId参数获取评论报错如何解决
报错原因
你遇到的报错核心原因是在组件的渲染逻辑中直接调用了会修改Redux状态的Action方法。DishDetail渲染过程中调用fetchComments会触发Redux状态更新,进而更新被Connect包裹的Main组件的props,属于渲染一个组件时同步更新另一个组件的冲突场景,触发了React的生命周期保护机制。
现有代码问题
- Main组件的
componentDidMount里调用的fetchComments()没有传入plateId参数,此时发出的请求地址本身就是错误的,属于无效调用 - 你把
fetchComments放在DishDetail的渲染逻辑里直接执行,属于在渲染阶段执行副作用操作,违反React的生命周期规范
正确实现方案
两种方案任选一种即可:
方案1:在路由匹配组件中触发请求(推荐,无需修改DishDetail组件)
把原本的纯渲染函数plateInfo改成带副作用处理的组件,在组件挂载时调用请求方法:
- 首先修改Main组件内的
plateInfo定义,增加副作用处理逻辑:
// 改为函数组件,用useEffect处理副作用 const PlateInfo = ({match, fetchComments, plates, comments}) => { const currentPlate = plates.plates.filter(item => item._id === match.params.plateId)[0] // 组件挂载、plateId变化时触发评论请求 React.useEffect(() => { if(currentPlate?._id) { fetchComments(currentPlate._id) } }, [currentPlate?._id, fetchComments]) return ( <DishDetail plate={currentPlate} comments={comments.comments} /> ) }
- 调整Route的渲染逻辑,把需要的props传递给PlateInfo:
<Switch> <Route exact path="/menu/:plateId" render={({match}) => <PlateInfo match={match} fetchComments={this.props.fetchComments} plates={this.props.plates} comments={this.props.comments} /> } /> </Switch>
- 删除Main组件
componentDidMount里的无效调用this.props.fetchComments()即可。
方案2:在DishDetail组件内部触发请求
如果你的业务逻辑更适合在详情组件内触发请求,就用这个方案:
- 修改plateInfo函数,把fetchComments传递给DishDetail:
const plateInfo = ({match}) =>{ const currentPlate = this.props.plates.plates.filter((item) => item._id === match.params.plateId)[0] return( <DishDetail plate={currentPlate} comments={this.props.comments.comments} fetchComments={this.props.fetchComments} /> ) }
- 在DishDetail的生命周期里执行请求:
如果是类组件:
componentDidMount() { if(this.props.plate?._id) { this.props.fetchComments(this.props.plate._id) } }
如果是函数组件:
useEffect(() => { if(props.plate?._id) { props.fetchComments(props.plate._id) } }, [props.plate?._id, props.fetchComments])
- 同样删除Main组件
componentDidMount里的无效fetchComments调用。
内容的提问来源于stack exchange,提问作者Anis
相关产品推荐
相关产品推荐

