在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)
})
}
提前谢谢
答案 0 :(得分:1)
执行此操作的最简单方法可能是通过引入另一个操作,您可以通过执行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))
新动作" userInfoUpdated"然后,您可以通过执行window.location.href =' ...'来处理redux中间件。的事情。
答案 1 :(得分:1)
如果您从thunk中返回fetch
承诺,那么您可以从调用方继续承诺链。假设updateUserInfo
返回获取承诺,修改了代码:
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
)做了太多的事情。单一责任委托人及其所有。
答案 2 :(得分:0)
这样做的方法不需要手动订阅商店而且不需要任何中间件(如其他答案所示)可以是:
减速机:
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。
答案 3 :(得分:0)
使用 react-query,它有更多的功能来获取数据和支持你的需求
答案 4 :(得分:-1)
将您的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之前,您需要阅读their documentation and tutorial。 subscribe
是Redux使用方式的基本部分之一。