2016-03-02 1 views
1

Извините за мой английский, надеюсь, вы меня поймете.Что делать, если действие зависит от другого действия async в Redux?

Я использую redux-thunk для асинхронных действий.

// actionA.js 
export function actionA() { 
    return fetch('api call') 
      .then((data) => ({ 
      type: 'actionA', 
      data: data 
      })) 
} 

// reducer.js 
export function reducer(state, action) { 
    ... 
    if(action.type === 'actionA') { 
    return { 
     ..., 
     dataA: action.data, 
     ... 
    }; 
    } 
} 

// actionB.js 
export function actionB() { 
    return (dispatch, getState) => { 
    if(!getState().dataA) { 
     dispatch(actionA()); 
    } 
    doSomethingWithDataA(getState().dataA); 
    }; 
} 

В некоторых случаях, мне нужно лишь отправить actionA без диспетчерских actionB. Но когда я отправляю actionB, actionB будет использовать dataA, а dataA создан actionA. Так что в actionB, я проверю, есть ли dataA в Store, если нет, я отправлю actionA. Но actionA - это асинхронное действие, я не могу получить, когда сделано actionA. Итак, как бороться с этой проблемой?

ответ

1

Вообще говоря, вы хотите сделать что-то, когда dataA готов и actionB случилось. Вы можете сделать это с помощью middleware

function myMiddleware() { 
    return store => next => action => { 
     const dataA = store.getState().dataA; 
     if(store.getState().dataA && action.type === 'actionB') { 
      doSomethingWithDataA(dataA); 
     } 
    }; 
} 

Тогда ваш actionB превращается в следующий

function lazyFetchDataA() { 
    return (dispatch, getState) => { 
     if(!getState().dataA) { 
      return dispatch(actionA()); 
     } else { 
      return Promise.resolve(); 
     } 
    } 
} 

export function actionB() { 
    return (dispatch, getState) => { 
     lazyFetchDataA().then(() => dispatch({type: 'actionB'})) 
    } 
} 

Это выглядит сложно, но теперь у вас есть маленькие кусочки кода в правильных местах, которые делают свое дело.

Возможно, вам не нужно делать такую ​​сложную вещь, если вы предоставите более подробную информацию о своем doSomethingWithDataA, я бы дал лучший ответ.

0

Этот подход может помочь, обратите внимание, что я буду использовать polyfill fetch, чтобы вернуть обещание для запроса aysnc.

function actionA(dataA) { 
    return { 
    type: 'actionA', 
    data: dataA 
    }; 
} 


export function actionB() { 
    return (dispatch, getState) => { 
    if(!getState().dataA) { 
     return fetch('api call') 
      .then((data) => { 
      dispatch(actionA(data)) 
      }) 
      .catch((error) => {// handle error}) 
    } 
    return doSomethingWithDataA(getState().dataA); 
    } 
} 
+0

Фактически в 'fetchDateFromServer()' из 'actionA', я просто использую полис заполнения. И проблема в некоторых случаях, мне нужно отправить 'actionA' без отправки' actionB'. – hronro

Смежные вопросы