【发布时间】:2020-06-16 05:33:59
【问题描述】:
我在顶层有一个 App 组件,然后在该组件中,我有一个名为 ErrorMessages 的组件。
我将 App 组件的状态放入上下文中,然后在我的应用程序的其他位置,如果发生错误,我会在 App 组件的上下文中设置错误。
App 组件随后会通过 prop 将错误传递给ErrorMessages,然后会显示错误消息。
问题是,我似乎无法清除错误消息。
目前我尝试的是,使用useEffect的清理机制来清除errorMessages。
假设我有一个名为UserRegistration 的组件,用户没有输入电子邮件地址,我设置了一个错误“需要电子邮件地址”,这样显示就好了。
现在,当UserRegistration 被卸载时,我想从App 上下文中清除错误消息。
我怎样才能做到这一点?
这是我的应用组件:
class App extends React.Component {
// For errors in the format of:
// [{message: "first_name missing..."}, {message: "Email address in use..."}]
setErrorMessages = (errors) => {
this.setState({errors}) }
// Other messages not in the format above. Can set "alert-warning" or
// "alert-success" type messages.
setStatusMessage = (statusType, statusMessage) => {
this.setState({statusType, statusMessage}) }
clearAllMessages = () => {
this.setState({errors: [], statusType: null, statusMessage: null}) }
setAuthToken = () => {}
setLoaded = (val) => { this.setState({loaded: val}) }
state = {
user: {},
loaded: false,
errors: [],
statusType: null,
statusMessage: null,
setErrorMessages: this.setErrorMessages,
clearAllMessages: this.clearAllMessages,
setStatusMessage: this.setStatusMessage,
setLoading: this.setLoading,
setLoaded: this.setLoaded,
setAuthToken: this.setAuthToken,
}
render() {
return (
<div className="App container">
<React.StrictMode>
<AppContext.Provider value={this.state}>
<BrowserRouter>
{this.state.statusMessage ?
<div className={"alert alert-" + this.state.statusType}>{this.state.statusMessage}</div> : null}
<ErrorMessages list={this.state.errors} />
{!this.state.loaded ? <LoaderWidget /> : null }
<IssueBrowser />
</BrowserRouter>
</AppContext.Provider>
</React.StrictMode>
</div>
);
}
}
如果我在较低级别的组件中使用useEffect 的清理机制,则会出现“超出最大深度”错误,并且页面会挂起。
这是我调用 useEffect 的组件:
const UserRegistration = (props) => {
const appContext = useContext(AppContext)
const history = useHistory();
const registerUser = (event) => {
event.preventDefault()
appContext.setLoaded(false)
let payload = {
first_name: event.target.first_name.value,
last_name: event.target.last_name.value,
email_address: event.target.email_address.value,
password: event.target.password.value }
Users.create(payload)
.then(response => {
appContext.setStatusMessage("success", "User successfully registered.")
appContext.setLoaded(true)
history.push('/')
})
.catch(error => {
if (error.response.data.messages) { appContext.setErrorMessages(error.response.data.messages) }
appContext.setLoaded(true)
})
}
useEffect(() => {
return function cleanup() {
appContext.clearAllMessages()
// this just seems to hang, the app goes into an infinite loop at this point and freezes.
}
})
return (
<form onSubmit={registerUser}>
<div className="form-group">
<label htmlFor="first_name">First Name:</label>
<input name="first_name" type="text" className="form-control" />
</div>
<div className="form-group">
<label htmlFor="last_name">Last Name:</label>
<input name="last_name" type="text" className="form-control" />
</div>
<div className="form-group">
<label htmlFor="email_address">Email Address:</label>
<input name="email_address" type="text" className="form-control" />
</div>
<div className="form-group">
<label htmlFor="password">Password:</label>
<input name="password" type="password" className="form-control" />
</div>
<div className="form-group">
<label htmlFor="password">Confirm Password:</label>
<input name="password" type="password" className="form-control" />
</div>
<div className="form-group">
<input className="btn btn-primary form-control" type="submit" value="Register" />
</div>
</form>
)
}
【问题讨论】:
-
你提到了一些关于
useEffect的事情,但你没有展示它。对了,你看error boundaries了吗? reactjs.org/blog/2017/07/26/… -
那是因为我知道我的方法行不通,而且我不想费心去尝试让它发挥作用,因为它可能构思不周。从概念上讲,我想知道其他人如何实现全局错误消息组件之类的东西。从高层次的角度来看,经验丰富的 React 开发人员如何实现这样的目标?可能不是我这样做的方式,所以我们不要为此烦恼。我发布了更多作为我想要实现的目标的示例。
-
对我来说这看起来不错。听起来您需要一个地方来存储所有(?)您的错误消息,以便您可以在根级别有条件地渲染内容,并且使用
context可以正常工作。听起来您在重复更新子组件的useEffect挂钩内的全局状态时遇到了问题,所以这就是您应该关注的问题。 -
我添加了更多代码,特别是我正在使用的组件
useEffect,据我所知,这应该可以工作,但似乎一切都停止了,它挂起,并创建一个无限循环。 -
你有无限循环,因为 useEffect 自己造成了一个效果,它自己触发了。
标签: reactjs