Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async actions in Redux

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; 
like image 396
Pablo Avatar asked Feb 20 '16 23:02

Pablo


People also ask

What is async actions in Redux?

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.

What are async actions?

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.

What is async action in react?

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 .

What are actions in Redux?

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.


2 Answers

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.

like image 63
rishat Avatar answered Oct 17 '22 19:10

rishat


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)) ); 
like image 38
Alexander Mills Avatar answered Oct 17 '22 20:10

Alexander Mills