Использование thunks в mapDispatchToProps

#reactjs #redux #react-redux

#reactjs #сокращение #реагирование-сокращение

Вопрос:

Мне интересно, как использовать создателей асинхронных действий в mapDispatchToProps for’ react-redux s connect . Я использую redux-thunk промежуточное программное обеспечение, и следующее мое mapDispatchToProps :

 function mapDispatchToProps(dispatch) {
    return {
        foo: function() {
            dispatch(someAction());

            return function asyncAction(dispatch, getState) {
                console.log("An async action!");
                dispatch(someOtherAction(getState().foo));
            };
        }
    }
}
  

Однако, когда я делаю вышеуказанное, асинхронное действие не выполняется. Каков правильный способ сделать это?

Ответ №1:

Я предлагаю объявить ваш фактический thunk ( someOtherAction ) по-другому. В следующем примере asyncAction это создатель асинхронного действия, который возвращает thunk. Затем thunk может отправлять другие действия (например, после разрешения promise).

 function asyncActionCreator () {
  return (dispatch, getState) => {
    dispatch(someAction());

    someAsyncStuff().then(() => {
      dispatch(someOtherAction(getState().foo);
    });
  }
}

function mapDispatchToProps(dispatch) {
  return {
    foo: () => dispatch(asyncActionCreator())
  }
}
  

Комментарии:

1. Наряду с этим: bindActionCreators утилита может использоваться для замены этой анонимной функции, а сам mapDispatch аргумент предлагает сокращение объектного литерала для привязки : connect(mapState, {foo : asyncActionCreator})(MyComponent) .

2. Как это может работать?? Это должно быть foo: () => asyncActionCreator()(dispatch)

3. @SadokMtir, этого не должно быть. В данном случае вы отправляете действия, созданные создателем действия asyncActionCreator . В этом примере используется redux-thunk , который изменяет подпись создателей вашего действия (или, скорее, добавляет thunks в качестве опции по сравнению с обычным объектом). Подпись этого thunk имеет dispatch в качестве своего первого параметра.

4. Этот пример не сработал в моем примере, где создатель действия возвращает обещание. export const sendInquiry = postalCode => dispatch => new Promise((resolve) => { dispatch({ type: ActionTypes.SEND_INQUIRY, postalCode, }); resolve(); }); Этот способ был решен: const mapDispatchToProps = dispatch => ({ actions: { sendInquiry: x => sendInquiry(x)(dispatch), }, });

Ответ №2:

Для полноты я собираюсь добавить это. Мне нужно было отправить 2 действия с использованием 1 action creator, но второе действие зависело от результата первого. Для второго действия также требовался доступ к другому фрагменту хранилища, поэтому я не мог использовать тот же редуктор, который я использовал для установки первого значения.

Мои mapDispatchToProps, использующие redux-thunk, в конечном итоге выглядели следующим образом:

 import constants from '../constants';

const mapDispatchToProps = (dispatch) => {
    return {
        setValuesToStore: (value) => {
            const firstAction = {
                type: constants.SET_FIRST_VALUE,
                value,
            }
            dispatch(firstAction)
            dispatch(secondAction())
            function secondAction() {
                return (dispatch, getState) => {
                    const state = getState()
                    dispatch({
                        type: constants.SET_SECOND_VALUE,
                        state,
                    })
                }
            }
        }
    }
}
  

Таким образом, мне не нужно было импортировать хранилище как модуль, который я нашел очень уродливым. Ничего страшного, просто надеюсь, что это поможет.

Ответ №3:

Хотя принятый ответ явно предпочтительнее, я считаю, что это небольшое изменение вашего кода также может помочь понять, как работает этот механизм:

 function mapDispatchToProps(dispatch) {
    return {
        foo: () => dispatch(function() { // <-- Note the dispatch!
            dispatch(someAction());

            return function asyncAction(dispatch, getState) {
                console.log("An async action!");
                dispatch(someOtherAction(getState().foo));
            };
        }()) // <-- Note the IIFE!
    }
}
  

Ваша исходная функция создания thunk (связанная с foo ) здесь должна быть немедленно вызвана и dispatch отредактирована, чтобы этот шаблон работал.