如何从"componentDidUpdate"中调用"调度"而不会陷入无限循环?



我正在制作一个非常简单的 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'
})
})
}
}
}

用我自己的话说,每次更新与此组件相关的状态的一部分(在本例中为loggedInprop(时,都会调用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
};

此流将避免任何循环或争用条件。

相关内容

  • 没有找到相关文章

最新更新