Isard
Isard

Reputation: 312

Redux action factory does not work with arguments

I decided to create reducer and action factories so I would not repeat code anymore. Reducer factory works fine. It's something like that:

const initialState = {
  loading: false,
  error: null,
  data: [],
  entity: null,
  query: null
}

const baseReducer = (name = '') => {  
  return (state = initialState, action) => {
    switch(action.type) {
      case `FETCH_ALL_${name}_BEGIN`:
      case `FETCH_ONE_${name}_BEGIN`:
        return {
          ...state,
          loading: true
        }
      case `FETCH_ALL_${name}_ERROR`:
      case `FETCH_ONE_${name}_ERROR`:
        return {
          ...state,
          loading: false,
          error: action.payload.error
        }
      case `FETCH_ALL_${name}_SUCCESS`:            
        return {
          ...state,
          loading: false,
          data: action.payload.data
        }
      case `FETCH_ONE_${name}_SUCCESS`:
        return {
          ...state,
          loading: false,
          entity: action.payload.data
        }
      default:
        return state;
    }
  }
}

Unfortunately action creators don't work if I pass any arguments to them. Here is my implementation:

import axios from 'axios';

export const actionFactory = (name, action, thunk) => () => {    
  return dispatch => {
    console.log('this one here does not work');
    dispatch({
        type: `${action}_${name}_BEGIN`
      }
    );

    return dispatch(thunk)
      .then(response => {
        dispatch({
          type: `${action}_${name}_SUCCESS`,
          payload: {
            data: response.data
          }
        })
      })
      .catch(error => {
        dispatch({
          type: `${action}_${name}_FAILURE`,
          payload: {
            error: error.message
          }
        })
      });
  }
}

And those are my two actions. First one works fine, but second one does not reach implementation of action factory. I have no idea why is this happening but it has something to do with passing arguments.

export const fetchUsers = actionFactory('USERS', 'FETCH_ALL', () => {
    return axios.get('http://localhost:8000/api/user')
  });

export const fetchUser = (body) => actionFactory('USERS', 'FETCH_ONE', () => {
  return axios.get('http://localhost:8000/api/user/' + body);
})

When I call both of them in a component, first one returns all users and second one does not run at all. Console.log statement does not work. Any ideas what can I do about it? I'm tired of repeating code and since reducer factory works I'd like not to leave it now.

Upvotes: 1

Views: 539

Answers (1)

Carlos Ruana
Carlos Ruana

Reputation: 2278

You are currying the second actionFactory (the second one returns a function when called).

So for the first one fetchUsers() is fine.

For the second one you need to call the function being returned after you pass the body argument. That would be:

fetchUser(body)()

Upvotes: 2

Related Questions