Как связать действия с промежуточным программным обеспечением Redux Promise?
Я довольно новичок в React и Redux. Я хочу объединить несколько вызовов API с использованием redux-обещания-промежуточного программного обеспечения и реализовал свои действия следующим образом:
locationActions.js:
import { visitLocation } from '../services/actionService';
export const VISIT_LOCATION = 'VISIT_LOCATION';
export const VISIT_LOCATION_PENDING = 'VISIT_LOCATION_PENDING';
export const VISIT_LOCATION_FULFILLED = 'VISIT_LOCATION_FULFILLED';
export const VISIT_LOCATION_REJECTED = 'VISIT_LOCATION_REJECTED';
const visitLocationAction = (characterId, location) => ({
type: VISIT_LOCATION,
// visitLocation returns a new promise
payload: visitLocation(characterId, location)
});
export { visitLocationAction as visitLocation };
Я отправляю это действие из моего компонента React, используя mapDispatchToProps
:
const mapDispatchToProps = dispatch => (
bindActionCreators({ visitLocation }, dispatch)
);
Это работает! Тем не менее, я хочу отправить еще одно действие после visitLocation
улажено и выполнено. Я не могу позвонить Promise.then()
потому что это не обеспечивает dispatch
метод, поэтому не "привязывать" мои действия к редуктору.
Учебники упоминают, что я должен позвонить dispatch(secondAction())
но у меня нет доступных отправителей в моих действиях создателей.
Может кто-нибудь указать мне, что я скучаю?
Редактировать:
Как предложено в первом ответе, я попробовал следующий подход:
import { visitLocation } from '../services/locationService';
import { fetchSomething } from '../services/otherService';
const visitLocationAction = (characterId, location) => {
return (dispatch) => {
return dispatch(visitLocation(characterId, location))
.then(() => dispatch(fetchSomething()));
};
};
export { visitLocationAction as visitLocation };
Но я получил action: undefined и следующую ошибку:
Error: Actions must be plain objects. Use custom middleware for async actions.
at dispatch (redux.js:200)
at redux-logger.js:1
2 ответа
Учебники упоминают, что я должен позвонить
dispatch(secondAction())
но у меня нет доступных отправителей в моих действиях создателей.
Позвольте мне сначала ответить на эту часть вашего вопроса. Как уже упоминалось в первом ответе, вам нужно Redux Thunk, промежуточное программное обеспечение, чтобы использовать dispatch
в твоих действиях создатели.
По умолчанию создатели действий Redux возвращают простые объекты, например:
const returnsAnObject = () => ({
type: 'MY_ACTION'
payload: ...,
meta: ....
})
С Redux Thunk создатели действий могут по существу возвращать функции. Функция, которая возвращает функцию, называется "thunk", отсюда и название Redux Thunk.
const returnsAFunction = (dispatch) => dispatch({
type: 'MY_ACTION'
payload: ...,
meta: ....
})
В конкретном случае Redux Thunk вы возвращаете dispatch
функция. Redux Thunk позволяет вам вернуться dispatch
предоставляя его в качестве параметра для ваших создателей действий.
Но я получил
action:undefined
Давайте распакуем это. Мы знаем - благодаря Redux Thunk- вы можете связать несколько действий вместе, используя dispatch
, Однако, как вы упомянули в отредактированном вопросе, вы все равно получаете ошибку "простой объект".
Error: Actions must be plain objects. Use custom middleware for async actions.
at dispatch (redux.js:200)
at redux-logger.js:1
Это потому что ты звонил dispatch
с объектом Promise, а не простым объектом.
const visitLocationAction = (characterId, location) => {
return (dispatch) => {
return dispatch(visitLocation(characterId, location))
// Yes, it is correct to call dispatch here
// However, `dispatch` accepts plain objects, not Promise objects
.then(() => dispatch(fetchSomething()));
};
};
Чтобы решить эту проблему, просто измените вашу вторую отправку, чтобы использовать простой объект:
const visitLocationAction = (characterId, location) => {
return (dispatch) => {
return dispatch(visitLocation(characterId, location))
.then(() => dispatch({{
type: 'VISIT_LOCATION_SECOND_TIME'
payload: fetchSomething()
}));
};
};
Как упомянуто в документации по промежуточному программному обеспечению redux -обещания, промежуточное программное обеспечение может быть объединено с Redux Thunk для создания цепочки действий создателей.
Таким образом, вы можете написать свое действие как:
const secondAction = (data) => ({
type: 'SECOND',
payload: {...},
})
const thirdAction = (data) => ({
type: 'THIRD',
payload: {...},
})
const firstAction = () => {
return (dispatch) => {
return visitLocation(characterId, location)
.then((data) => dispatch(secondAction(data)))
.then((data) => dispatch(thirdAction(data)))
}
}
или используйте async/await
const secondAction = (data) => ({
type: 'SECOND',
payload: {...},
})
const thirdAction = (data) => ({
type: 'THIRD',
payload: {...},
})
const firstAction = async () => {
return (dispatch) => {
const data = await visitLocation(characterId, location));
dispatch(secondAction(data))
dispatch(thirdAction(data))
}
}
и затем используйте его, как вы упомянули:
const mapDispatchToProps = dispatch => (
bindActionCreators({ firstAction }, dispatch)
);