web-dev-qa-db-ja.com

ReactJS + Redux:ディスパッチが完了するまで待ってから次のステップに進むにはどうすればよいですか?

ReactJS + Reduxプロジェクトには、APIリクエストを行うメソッドがあります。成功した場合は、別のアクションクリエーターを派遣し、終了するまで待ちます。それが完了したら、次のステップに進みます。

現在、次のコードは別のAPI呼び出しを行うディスパッチを実行しますが、ディスパッチによって状態が更新される前でも、すぐに_window.location.href ='http://localhost:3005/#/Home'_を実行し、その後ディスパッチが完了します。

では、次のコード行_window.location.href ='http://localhost:3005/#/Home'_を実行する前に、dispatch(actions.updateUserInfo(userInfo.username))が完了するまでどのように待つことができますか?

アクションの作成者は次のとおりです。

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

前もって感謝します

6
user3259472

おそらく、これを行うための最も簡単な方法は、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))

次に、window.location.href = '...'を実行することにより、reduxミドルウェアで処理する新しいアクション「userInfoUpdated」。

1
WTK

サンクからfetch promiseを返すと、呼び出し元からpromiseチェーンを続行できます。 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)
  })
}

しかし、最初のサンク(updateUserInfo)があまりにも多くのimoを実行しているため、2番目のサンク(loggingIn)への呼び出しをReactコンポーネントに移動します。単一責任プリンシパルおよびそのすべて。

1
Rick Jolly

ストアに手動でサブスクライブする必要がなく、ミドルウェアを必要としない(他の回答で示唆されているように)これを行う方法は、次のとおりです。

レデューサー:

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は呼び出されません。

0
fabio.sussetto

あなたの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の使用方法の基本的な要素の1つです。

0
Don Rhummy