Byrd
Byrd

Reputation: 907

Why can I access an array in my Redux store?

I have a Redux reducer and I am trying to nest an array of objects within my reduce, but it is breaking. I don't seem to have access to anything in the array. However, if I return an array instead of an object from the reducer it works fine.

const friendReducer = (state = {}, action) => {
  console.log(action);
  switch (action.type) {
    case 'GET_FRIENDS':
      return {
        list: [
          ...state,
          ...action.payload,
        ],
      };
    default:
      return state;
  } 
};

export default friendsReducer;

When I try to access the list in my connected components, I can't access the Array#splice method or Array#length property. Here are other relevant parts of the code:

const mapStateToProps = (state) => {
  return {
    friends: state.friends,
  }
};

const rootReducer = {
  friends: friendsReducer,
};

const store = createStore(
  combineReducers({
    ...rootReducer,
    router: routerReducer,
  }),
  {}, // initial state
  compose(
    applyMiddleware(thunk),
    applyMiddleware(routerMiddleware(history)),
    // eslint-disable-next-line no-underscore-dangle
    (typeof window.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined') ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f,
  ),
);

export default store;

Upvotes: 2

Views: 1413

Answers (1)

Andrew Li
Andrew Li

Reputation: 57964

You've got a few problems. For one, friendsReducer's slice of state returns an object, not an array. So your state looks like this:

{
  friends: {
    list: […]
  }
}

So when you mapStateToProps, it should look like this if you want the array:

return {
  friends: state.friends.list //not state.friends, that's an object
}

Next, also notice that your initial state doesn't contain list in it:

const friendReducer = (state = {}, action) => { … }

So when you first try to access the length of list, there will be no list property, so you have to set it as an empty array inside your initial state. Always set up your initial state with all the properties:

const friendReducer = (state = { list: [] }, action) => { … }

Finally, you're spreading the wrong property of state in your reducer:

case 'GET_FRIENDS':
  return {
    ...state, //here use ...state to spread previous state
    list: [
      ...state.list, //not state, use state.list to spread previous list
      ...action.payload,
    ],
  };

You want to spread the old list, so you're supposed to spread state.list, not state itself. Also, you can add ...state outside of list to spread the previous state for good measure, assuming you'll have more than one action, though its good practice nonetheless.

Upvotes: 3

Related Questions