【发布时间】:2021-03-20 04:09:51
【问题描述】:
我遇到了一个小问题,我确实解决了这个问题,但我真的在寻找更好的解决方案!
假设你有一个 Parent A 组件,它的作用是调度一个动作来获取数据。
class ParentA extends Component {
constructor(props) {
super(props)
const { dispatch } = this.props;
dispatch(actionRequest({ clientId: props.match.params.customerId }))
}
render() {
const { customer, isFetching } = this.props;
if(isFetching){
return <Spinner />
}
if(!customer){
return null
}
return <CustomerDetailsPage customerId={this.props.match.params.customerId} customer={customer} {...this.props} />
}
}
export default connect(state => ({
customer: getClient(state),
isFetching: isClientFetching(state)
}))(ParentA)
这里没什么复杂的。
假设我在 api 调用之前在我的 saga 中调度了一个动作,将 isFetching 设置为 true,并在 api 调用成功或错误之后将 isFetching 返回到错误的。 当然,我对这个 reducer 的初始状态 isFetching 为 false。
我的动作创建者看起来像这样(不要注意包装减速器,重要的是不同的动作)
const setFetching = isFetching => state => state.set('fetching', isFetching)
export default createReducer(initialState, {
[actionSuccess]: [setClient],
[actionRequest]: [setFetching(true)],
[actionFulfill]: [setFetching(false)],
})
问题,总结起来就是这样一个:当reducer处于初始状态时,没有问题,因为我将第一次放入获取的数据,所以在第一次渲染时它是null。
问题是当 ParentA 组件卸载时,redux 仍然存储以前的值。 所以当我回到ParentA时,connect函数中的选择器已经有了值。
它最终导致 ParentA 的子级的第一次渲染无用,因为 isFetching 是错误的,并且在我的示例中 customer 不是我刚才所说的 null。
最后它会导致一个无用的子渲染,但是想象一下 ParentA 的子获取自己的数据,然后它会导致从子获取 2 次!
我通过将 isFetching 和 customer 在树中更深地移动到孩子中解决了这个问题,但我想避免拆分我的道具并在 ParentB 中处理这个问题。 我无法记住 ParentA,因为 isFetching 确实在变化。 你最终会提出什么建议?
【问题讨论】:
标签: reactjs redux react-redux redux-saga