Search code examples
javascriptpromisereduxaxiosredux-promise

Reducer returns undefined when using redux-promise and axios


I'm having this issue when I'm trying to invoke a callback after the promise resolves (using .then) It turns out that this gives my const request some kind of different promise that reducer returns as undefined:

action:

   export function lookup(company, callback) {
      const id = company.textfield;
      const url = `${ROOT_URL}${id}`;

      const request = axios.get(url)
       .then(() => callback())

      return {
        type: LOOK_UP,
        payload: request,
        meta: id
     };
 }

reducer:

import { LOOK_UP } from '../actions/index';

export default function(state = {}, action) {
    switch (action.type) {
        case LOOK_UP:
            const data = action.payload.data;
            const id = action.meta;

            if (data.Success === true) {
                return { ...state, [id]: data.CompanyInformation };
            } else {
                return state;
            }
    }
    return state;
}

As you can see I pass the data from API that axios get to my reducer. After this I set the state and I need to invoke that callback that is in 'actions' (it creates then another action call inside component). Unfortunatelly, I got error that in reducer const data = action.payload.data is undefined.

When I don't use this callback everything works fine, but the case is that I neet to invoke that callback only after this reducer returns new state.


Solution

  • request is equals to this whole statement:

    const request = axios.get(url)
       .then(() => callback())
    

    So if callback() doesn't return something, then the promise will resolve to nothing. I assume you are fetching some data with this call, so you need to pass that data on, or else your reducer will never get it. Like so:

    const request = axios.get(url)
       .then((dataFromRequest) => { 
         callback(); 
         return dataFromRequest; 
    });
    

    Or you can separate the two and write something like:

    const request = axios.get(url);
    request.then(() => callback());
    
    return {
        type: LOOK_UP,
        payload: request,
        meta: id
     };
    

    Compare the promises in the snippet below:

    const promisedData = () => Promise.resolve(42);
    
    promisedData()
      .then(data => console.log('Resolved data is ', data));
    
    
    const promisedTrasformedData = () => 
       Promise.resolve(700)
       .then(data => data - 34);
       
       
    promisedTrasformedData()
      .then(transformedData => console.log('Transformed data is ', transformedData));
      
      
    
    const promisedAndLostData = () => 
      Promise.resolve(42)
     .then(data => returnNoting())
    
    function returnNoting() { };
    
    promisedAndLostData()
     .then(lostData => console.log('Lost data: ', lostData))