Search code examples
javascriptreactjsreduxredux-thunk

React, Redux, Thunk


I have been now struggling with this piece of code for quite a while, searching online through stackoverflow and the docs, and there is something I am just not getting...

I am basically using react redux with thunk. This is the code:

export function initializeApp(){

    return function (dispatch, getState){

        console.log(getState().weekending.weekending);
        const promisesArray = stateConfig.charts.map(option=>{
            return ()=> new Promise(resolve=>{
                ()=>dispatch(getChart(option,getState().weekending.weekending))
                resolve()}
            )
        });

        const delay = (ms) => new Promise(resolve =>
            setTimeout(resolve, ms)
        );

        console.log(promisesArray);
        return Promise.all(
            promisesArray
            ).then(delay(10000)
            ).then(()=>{console.log(getState().charts)}
            )
        // .then(()=>dispatch(appLoaded()))

    }
}

I am trying to create an array of actions that needs to get executed at the same time. I read with redux thunk, you can use Promise.all. I am creating an array of dispatch functions, which runs getChart, which is basically an action that pulls in the dataPoints of a chart and puts it into the store. The amount of functions to get executed is based on stateConfig.charts which is the array which contains all the data needed for the pulling of the charts as well as the options of each individual chart.

When I do this, it somehow never dispatches the functions, I am not sure why. If I change the code around in any way, I get: 1) dispatch(...).then is not a function 2) Error: Actions must be plain objects. Use custom middleware for async actions.

I think there is something fundamental I am not grasping here.

Any help is appreciated.

Ml, Vincent

EDIT: After the help I got, I ended up with this:

    function appLoaded(dispatch){
        return new Promise(resolve=>{
            dispatch({type: ActionTypes.APP_LOADED});
            resolve();
        })
    }

    function getChart(options,weekending,dispatch){
        return new Promise((resolve,reject)=>{
            const {controller, action, payload } = options;
            payload.weekending = weekending;
            const SocketConnection = {controller,action,payload};
            console.log(SocketConnection)
            socket.emit(SocketRequest, SocketConnection, (data) => {
                const dataPoints = data.map((row,index)=>{return{x:index, label:row.name, y:timeToDecimal(row.value), labelValue: row.value, id:row.id }})
                    const payload = {
                        ...options, data: {...options.data.primary, dataPoints,}
                    }
                dispatch({type: ActionTypes.ADD_CHART, payload});
                resolve();
            })
        })
    }

    export function initializeApp(){
        return function (dispatch, getState){
            const promisesArray = stateConfig.charts.map(option=>getChart(option,getState().app.weekending,dispatch))
            const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
            return Promise.all(
                promisesArray
                ).then(appLoaded(dispatch)
                ).then(()=>delay(3000)
                ).then(()=>{console.log(getState().charts)}
                ).then(()=>{console.log(getState().app)}
                )
        }
    }

Solution

  • Rather than trying to dispatch an array of actions, i'd recommend you just directly do whatever async stuff it is you need. For example:

    function initializeApp(){
      return function (dispatch, getState) {
        const weekending = getState().weekending.weekending;
        const promisesArray = stateConfig.charts.map(option => {
          return doWork(option, weekending);
        })
    
        Promise.all(promisesArray)
          .then(charts => {
            dispatch(appLoaded(charts))
          })
      }
    }
    
    
    function doWork(option, weekending) {
      // maybe it looks something like this? Substitute with whatever you need to do, 
      //   and make sure to return a promise
      return http.get('someUrlBasedOnOptionAndWeekending')
        .then(response => response.data);
    }