大约一年前,我学会了React
和Redux
,直到最近才大量使用它们。我很惊讶地发现React
和Redux
都有不少变化。
我注意到的第一件事是我不能再使用componentWillReceiveProps
生命周期方法,它告诉我我需要使用一些奇怪的getDerivedStateFromProps
方法,这并不能真正解决我当前的问题。
基本上,我有一个寄存器功能,dispatches
3actions
-REGISTER_REQUEST
、REGISTER_SUCCESS
和REGISTER_FAIL
。我的用户Reducer中还有3个标志 -registering
,registered
,registerError
。
在我的Register
组件中,我想执行以下操作:
- 当
registering
为 true 时,添加加载动画 - 当
registering
为假而registered
为真时,将用户重定向到/profile
路由 - 当
registerError
为 true 时,从redux store
获取错误并将其设置在组件的state
中。
我的第一个方法如下:
componentWillReceiveProps() {
if(this.props.user){
if(this.props.user.registered && !this.props.user.registering){
this.props.history.push("/jobs")
}
}
if(this.props.user.registerError){
this.setState({error: this.props.user.registerErrorMessage})
}
}
这并没有像我预期的那样成功。正如我上面提到的,它告诉我我不再被允许使用componentWillRecieveProps
.
我的下一个猜测是使用componentDidUpdate
方法,但在该方法中,我不能调用setState
,因为它会导致臭名昭著的state loop error
。我以前曾解决过此错误,但并非没有做很多我不喜欢的黑客事情。
我最终确实通过创建一个允许我从组件外部重定向用户(寄存器功能(的history helper
来解决此问题,但这最终导致react router
出现更多问题,并且它没有解决我的问题将registerErrorMessage
设置为组件state
。
那么在 React 和 Redux 中执行此操作的正确方法是什么?我真的试图避免使用黑客技巧来解决这些问题,因为几乎总是他们后来过来咬我的屁股。
虽然我看不出为什么您需要将错误消息保存在组件的状态中,而不仅仅是从 redux 存储中获取错误并将其显示给用户,但您可以在函数内部调用this.setState
componentDidUpdate
但为了避免状态更新和重新渲染的无限循环,您需要有条件地更新状态。
假设 redux 存储中的registerError
和组件状态中的error
最初都是null
的,componentDidUpdate
函数内部,检查this.state.error
是否等于从 redux 存储中注册错误。如果它们不相等,请更新状态。
componentDidUpdate(prevProps, prevState) {
if (this.state.error != this.props.registerError) {
this.setState({ error: this.props.registerError });
}
}
演示:
在此演示中,有一个Register
组件,它调度一个操作以从 jsonplaceholder API 获取用户。当 HTTP 请求启动时,将调度REGISTER_REQUEST
操作,该操作将 redux 存储中的registering
状态设置为 true。如果成功获取用户,则会调度REGISTER_SUCCESS
操作。如果发生错误,将调度REGISTER_ERROR
操作。当出现错误时,该错误将保存在组件内部的状态Register
并且还会向用户显示。
为了在发出 HTTP 请求时产生错误,我已将 API URL 从
"https://jsonplaceholder.typicode.com/users/1" // correct URL
自
"https://jsonplaceholder.typicode.com/user/1" // incorrect URL
当props
由于 redux 存储中的更改而更改时,组件将再次呈现。因此,您应该将此逻辑放在render
函数中。由于调用setState
将调用另一个渲染,因此您应该只使用props
中的错误值,而不是将其保存在状态中。