在ReactJS + Redux项目中,我有一个方法,它使API请求。如果成功,我想派遣另一个动作创建器并等待它完成。当它完成后,进入下一步。
当前,下面的代码执行调度,它调用另一个API,但甚至在通过调度更新状态之前,它立即执行window.location.href ='http://localhost:3005/#/Home'
,然后调度完成。
那么我怎么能等到dispatch(actions.updateUserInfo(userInfo.username))
完成后再执行下一行代码window.location.href ='http://localhost:3005/#/Home'
呢?
下面是动作创建器:
loggingIn(userInfo) {
var userInfoBody = {
'username': `${userInfo.username}`,
'password': `${userInfo.password}`
}
var configuration = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userInfoBody)
}
return function(dispatch) {
fetch('https://backendserver.com:8080/creds', configuration)
.then(response => response.json())
.then(response => {
//Would like to finish this dispatch completely before start executing window.location.href ='http://localhost:3005/#/Home'
dispatch(actions.updateUserInfo(userInfo.username))
window.location.href ='http://localhost:3005/#/Home'
})
.catch((error) => {
console.log("Error: ", error)
})
}
提前感谢
要做到这一点,最简单的方法可能是引入另一个操作,您将通过执行window.location.href = '…的东西。
由于redux可以被认为是"单线程的",因此可以确保在每个调度调用之间完全更新状态树。
dispatch(actions.updateUserInfo(userInfo.username))
// It's guaranteed that at this point your updateUserInfo action is handled and state tree is updated
dispatch(actions.userInfoUpdated(userInfo.username))
新的操作" userinfoupupdated ",你可以在redux中间件中通过执行window.location.href = '…的东西。
如果您从您的服务器返回fetch
承诺,那么您可以继续从调用者返回承诺链。修改代码,假设updateUserInfo
返回fetch承诺:
return function(dispatch) {
return fetch('https://backendserver.com:8080/creds', configuration)
.then(response => response.json())
.then(response => {
//Would like to finish this dispatch completely before start executing window.location.href ='http://localhost:3005/#/Home'
dispatch(actions.updateUserInfo(userInfo.username))
.then(() => {
window.location.href ='http://localhost:3005/#/Home'
})
})
.catch((error) => {
console.log("Error: ", error)
})
}
但是我会将调用移动到第二个thunk (updateUserInfo
)到React组件中,因为第一个thunk (loggingIn
)做得太多了。单一责任原则等等
一种不需要手动订阅存储且不需要任何中间件(如其他答案所建议的)的方法如下:
减速器:
function userReducer (state={ doneUpdating: false, userData: null }, action) {
if (action.type === 'UPDATE_USER_INFO') { // this is the action dispatched by updateUserInfo
return { ...state, userData: action.payload, doneUpdating: true }
}
}
组件:
class YourComponent {
componentWillReceiveProps (nextProps) {
if (!this.props.doneUpdating && nextProps.doneUpdating) {
window.location.href ='http://localhost:3005/#/Home'
}
}
// Rest of your component methods here...
}
function mapStateToProps (state) {
return { doneUpdating: state.userReducer.doneUpdating }
}
connect(mapStateToProps)(YourComponent)
基本上,在完成状态更新之后,设置一个标志。您的组件(与Redux连接)从状态读取该标志,并在componentWillReceiveProps
中检测更改并相应地做出反应(双关语)。根据您的情况,您可能需要在componentWillMount
中执行相同的检查/重定向逻辑。如果您需要在组件尚未挂载时调度用户更新操作,则需要这样做。在这种情况下,doneUpdating标志可以在组件被挂载之前变为true,并且componentWillReceiveProps不会被调用。
将window.location.href ='http://localhost:3005/#/Home'
放入订阅处理程序中。记得订阅我们的活动:
constructor(props, children)
{
TheStore.subscribe( this.listenForDispatch.bind( this ) );
}
listenForDispatch()
{
//Check the state is what you want
if ( TheStore.getState().someProp == "somevalue" )
{
//Call it here!
window.location.href ='http://localhost:3005/#/Home'
}
}
编辑:在您开始在代码中使用Redux之前,您需要阅读它们的文档和教程。subscribe
是如何使用Redux的基本部分之一
使用react-query,它有更多的功能来获取数据和支持您的需求