Асинхронные действия в Redux
У меня есть приложение React, мне нужно сделать ajax-вызов (чтобы узнать) в онлайн-службу (async) с помощью Redux.
Это мой магазин:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export default applyMiddleware(thunk)(createStore)(duedates);
Это действия:
import rest from '../Utils/rest';
export function getDueDatesOptimistic(dueDates){
console.log("FINISH FETCH");
console.log(dueDates);
return {
type: 'getDueDate',
dueDates
}
}
export function waiting() {
console.log("IN WAIT");
return {
type: 'waiting'
}
}
function fetchDueDates() {
console.log("IN FETCH");
return rest({method: 'GET', path: '/api/dueDates'});
}
export function getDueDates(dispatch) {
console.log("IN ACTION");
return fetchDueDates().done(
dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
)
}
И это редуктор:
export default (state = {}, action) => {
switch(action.type) {
case 'getDueDate':
console.log("IN REDUCER")
return state.dueDates = action.dueDates;
default:
return state
}
}
Я не понимаю, что я делаю неправильно. Действие отлично называется компонентом. Но затем я получаю эту ошибку:
Ошибка: действия должны быть обычными объектами. Используйте специализированное промежуточное программное обеспечение для асинхронных действий.
Думаю, я использую неправильное промежуточное ПО.
Что я делаю неправильно?
ИЗМЕНИТЬ
Теперь действие вызывает редуктор, но редуктор после изменения состояния не повторяет метод рендеринга
case 'getDueDate':
console.log("IN REDUCER")
return state.dueDates = action.dueDates;
Ответы
Ответ 1
Я думаю, вы должны использовать функцию compose
, чтобы она выглядела как
import {
createStore,
applyMiddleware,
compose
} from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export default compose(applyMiddleware(thunk))(createStore)(duedates);
Thunk позволяет создателю действия возвращать функцию вместо обычного объекта, поэтому вы используете его как
export function getDueDates() {
return dispatch => {
console.log("IN ACTION");
fetchDueDates().done(
dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
)
};
}
Вы возвращали объект Promise, это была одна из проблем. Другая часть заключалась в том, что утилизатор не применялся должным образом. Я уверен, что compose
должна решить проблему.
Ответ 2
Принятый ответ либо устарел, либо ошибочен, либо чрезмерно запутан. Ниже приведены документы по теме:
http://redux.js.org/docs/api/compose.html
чтобы мы могли сделать это следующим образом:
import {createStore, combineReducers, compose, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
const reducer = combineReducers({
user: userReducer,
items: itemsReducer
});
// here is our redux-store
const store = createStore(reducer,
compose(applyMiddleware(thunk))
);
Ответ 3
Я считаю, что возможно иметь рабочее решение без использования функции compose
. На основе документации из репозитория GitHub для redux-thunk
Решение работает для redux-thunk: ^2.0.0
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export function configureStore(initialState = {}) {
return createStore(
duedates,
initialState,
applyMiddleware(thunk)
);
}