#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
отредактирована, чтобы этот шаблон работал.