Async actions in Redux
Solution 1
I think you should be using compose
function, so it's like
import {
createStore,
applyMiddleware,
compose
} from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export default compose(applyMiddleware(thunk))(createStore)(duedates);
Thunk allows an action creator to return a function instead of plain-object, so you use it like
export function getDueDates() {
return dispatch => {
console.log("IN ACTION");
fetchDueDates().done(
dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
)
};
}
You were returning a Promise object, that was one part of the problem. Another part was that redux-thunk hasn't been properly applied. I bet compose
should get the problem solved.
Solution 2
The accepted answer is either outdated, wrong or over-convoluted. Here are the docs on the compose subject:
http://redux.js.org/docs/api/compose.html
so we can do it like this instead:
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))
);
Solution 3
I believe it is possible to have a working solution without using the compose
function too. Based on the documentation from the GitHub repo for redux-thunk
Solution works for 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)
);
}
Pablo
Updated on December 16, 2020Comments
-
Pablo over 3 years
I have a React App, I need to make an ajax call (in order to learn) to a online service (async) with Redux.
This is my store:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import duedates from './reducers/duedates' export default applyMiddleware(thunk)(createStore)(duedates);
This is the actions:
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)) ) }
And this is the reducer:
export default (state = {}, action) => { switch(action.type) { case 'getDueDate': console.log("IN REDUCER") return state.dueDates = action.dueDates; default: return state } }
I dont get what I'm doing wrong. The action is being called perfectly from the component. But then I get this error:
Error: Actions must be plain objects. Use custom middleware for async actions.
I guess I'm using wrong the react-thunk middleware. What am I doing wrong?
EDIT
Now the action is calling to the reducer, but the reducer, after changing state, is not re-running the render method
case 'getDueDate': console.log("IN REDUCER") return state.dueDates = action.dueDates;