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;
Redux Async Data Flow Then, we call dispatch() , and pass in something, whether it be a plain action object, a function, or some other value that a middleware can look for. Once that dispatched value reaches a middleware, it can make an async call, and then dispatch a real action object when the async call completes.
Media Server responds to an asynchronous action immediately. This means that you do not have to wait for a response if the action takes a long time. The response to an asynchronous action includes only a token. You can use this token to determine the status of the task through the QueueInfo action at a later time.
Async actions - React Async. Async actions. Fetching data for display alone isn't sufficient for most applications. You'll often also want to submit data back to the server, or handle other types of asynchronous actions. To enable this, React Async has the concept of a deferFn .
Redux data flow. Actions: Actions are a plain JavaScript object that contains information. Actions are the only source of information for the store. Actions have a type field that tells what kind of action to perform and all other fields contain information or data.
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.
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)) );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With