我正在制作一个非常简单的 React 组件,它显示从远程源获得的数据。在获取数据之前,它必须等待用户正确登录。以下是我尝试执行此操作的方法:
class MyComponent extends React.Component {
componentDidUpdate () {
if (this.props.loggedIn) {
api.getData()
.then(() => {
this.props.dispatch({
type: 'gotData'
})
}, (reason) => {
this.props.dispatch({
type: 'getDataFailed'
})
})
}
}
}
用我自己的话说,每次更新与此组件相关的状态的一部分(在本例中为loggedIn
prop(时,都会调用componentDidUpdate
,如果我看到用户已登录,我可以获取数据。
这实际上效果很好,除了一个主要问题:似乎调用dispatch
最终会再次触发componentDidUpdate
,所以我最终陷入了一个无限循环。我什至不必在任何地方监听这些调度事件,使用dispatch
函数的简单事实足以再次触发componentDidUpdate
。
我的猜测是调度执行我的根化简器,它在内部使用setState
,从而再次触发整个update
生命周期链。
这种事情通常是怎么做的?如何从componentDidUpdate
内部调用dispatch
而不会陷入无限循环?
解决此问题的一种简单方法是添加一个额外的标志,例如loggingIn
,您在异步操作之前设置(通过调度(并在之后重置。您还需要跟踪登录失败的时间,以区分这种情况与登录过程未启动的时间(除非您希望在失败时自动重新启动该过程(:
class MyComponent extends React.Component {
componentDidUpdate () {
const { loggedIn, loggingIn, loginFailed, dispatch } = this.props;
if (!loggingIn && !loggedIn && ! loginFailed) {
dispatch({
type: 'gettingData' // this one sets loggingIn to true, loggedIn to false, loginFailed to false
});
api.getData()
.then(() => {
dispatch({
type: 'gotData' // this one sets loggingIn to false, loggedIn to true, loginFailed to false
})
}, (reason) => {
dispatch({
type: 'getDataFailed' // this one sets loggingIn to false, loggedIn to false, loginFailed to true
})
})
}
}
}
如果您不希望在 redux 中设置此状态,您还可以在组件本身中存在此控件:
class MyComponent extends React.Component {
componentDidUpdate () {
const { loggedIn, dispatch } = this.props;
const { loggingIn, loginFailed } = this.state;
if (!loggingIn && !loggedIn && !loginFailed) {
this.setState({
loggingIn: true
})
api.getData()
.then(() => {
this.setState({
loggingIn: false,
loginFailed: false
});
dispatch({
type: 'gotData'
})
}, (reason) => {
this.setState({
loggingIn: false,
loginFailed: true
});
dispatch({
type: 'getDataFailed'
})
})
}
}
}
可以使用loggingIn
标志向用户显示微调器,或使用loginFailed
标志显示消息(如果这符合你的 UX(。
当您收到登录状态时,将您的 API 调用移动到操作!像这样:
api.getUserLoggedInStatus().then((status) => {
dispatch({
type: 'loggedInStatus',
status
});
api.getData.... // and dispatch
};
此流将避免任何循环或争用条件。