ReactJS + Redux:在进入下一步之前如何等待调度完成?

时间:2016-10-12 20:11:42

标签: javascript reactjs redux react-jsx react-redux

在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)
      })
    }

提前谢谢

5 个答案:

答案 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 tutorialsubscribe是Redux使用方式的基本部分之一。