Second argument to createStore in redux

Hi campers,

I am reading through the redux doc. Specifically about the createStore function. The function signature of createStore is:

createStore(reducer, [preloadedState], [enhancer])

What i don’t understand is the explanation of the second argument preloadedState.

[ preloadedState ] (any) : The initial state. You may optionally specify it to hydrate the state from the server in universal apps, or to restore a previously serialized user session. If you produced reducer with combineReducers , this must be a plain object with the same shape as the keys passed to it. Otherwise, you are free to pass anything that your reducer can understand.

What exactly does the statement plain object with the same shape as the keys passed to it mean? What is an object shape?
There is a Stackoverflow question here about the shape of an object but nobody has answered it yet.

{
  this: 0,
  is: 0,
  the: {
    shape: 0,
    of: 0,
    some: 0,
    object: 0
  },
}

Same shape:

{
  this: 1,
  is: 1,
  the: {
    shape: 1,
    of: 1,
    some: 1,
    object: 1,
  },
}

Literally, the shape. I guess there isn’t an answer because it’s literally dictionary definition of “shape”, it’s the shape of the thing. The state of Redux has certain properties in a certain shape. If you put an object of a different shape in (like with different keys or keys in different places) it’s not going to work properly because it won’t be the same. Like maybe you want to initialise the state with all the properties set to some default value, but in the app they get populated with other values

1 Like

Thanks for the reply. I was motivated to ask this question because i kept getting the warning below whenever i tried to use combineReducer and passed thepreloadedState

 The preloadedState argument passed to createStore has unexpected type of "Array". Expected argument to be an object with the following keys: "commentReducer", "postReducer"

I have two reducers commentReducer and postReducer which i want to merge using combineReducer.

function commentReducer(state = [], action) {
  switch (action.type) {
    case SET_COMMENTS:
      return [...state, ...action.comments];
    default:
      return state;
  }
}

function postReducer(state = [], action) {
  switch (action.type) {
    case SET_POSTS:
      return [...state, ...action.posts];
    default:
      return state;
  }
}

const rootReducer = combineReducers(
  { commentReducer, postReducer }, [ ]
);

How can i merge the two reducers and pass preloadedState to combineReducers to remove the above warning? It seems there is something i am missing here.

I think you’re not quite getting what this is in front of you – I don’t mean that in a derogatory sense, I think this is quite normal when learning Redux.

First thing is that createStore takes a reducer function, you can only have one. So you need to join postReducer and commentReducer into one big switch statement rather than two. So if you get SET_POSTS going into the switch it sets posts and if you get SET_COMMENTS it sets comments. You can’t just have state as an array, or they’d all get mixed up, so combineReducers joins the switches together but instead of a single array as state, it returns an object with a key for each reducer function:

const rootReducer = combineReducers({
  commentReducer: commentReducer,
  postReducer: postReducer,
}, []);

Can be thought of as creating this:

function rootReducer(state = { commentReducer: [],
postReducer: [],
}, action) {
  switch (action.type) {
    case SET_POSTS:
      const newPosts = [...state.postReducer, ...action.posts];
      return { ...state, postReducer: newPosts };
    case SET_COMMENTS:
      const newComments = [...state.commentReducer, ...action.comments];
      return { ...state, commentReducer: newComments };
    default:
      return state;
  }
}

So the shape of the state is

{
  commentReducer: [],
  postReducer: [],
}

Hopefully this also shows you that your reducers have very confusing names. Each of them is a function that resolves to a piece of state. Each piece of state is a list of things. One of those is an array of comments, one of those is an array of posts. It is emphasised with redux that reducer function must be pure. What this means is that given an input, the function will always return the same output. And in turn, this means that the function can always be replaced with its return value in the code: the function is the data. postReducer is just a list of posts; it’s not a special thing, it’s just a list of posts.

So commentReducer and postReducer are confusing names, because they aren’t what they are. They are comments and posts. They represent slices of the overall state, which will be an object with some keys.

So rename commentReducer to comments and postReducer to posts.

So now

const rootReducer = combineReducers({ comments, posts })

Which creates state that looks like this:

{
  comments: [],
  posts: [],
}

Thanks for taking time to reply. I though i would understand redux by reading the documentation like i did with react but i guess i was wrong. The redux doc , in my opinion, is full of unnecessary jargon making it more difficult to understand. I wish it was simple like react doc. I guess l will have to look for other tutorials to fully understand redux.

What do you mean by jargon and what are you stuck on? I’m not sure anything in the docs is unecessary, I just think most people coming to Redux don’t quite get it, because it doesn’t really do anything. This is maybe a bad metaphor but it’s like if arrays weren’t part of JS and you had to add an Array library, it would be very confusing, people wouldn’t see the point

Redux is a ridiculously simple thing (although it does complicate the resulting code, because it’s an extra layer). You create an object using createStore. The point of it is to prevent you modifying that object willy-nilly. So createStore also returns a function called dispatch. You can only update that object by sending actions into that dispatch function. There has to be something that takes each action and decides what the update to the state object should be, that’s a reducer finction

Hey there,

if you want to learn the concepts behind Redux,
have a look at the Redux Intro on egghead,
created by the original creator of Redux.

If you understand the concepts behind it, a lot of things will clear up!

Thanks. I will definitely check it out. I have never been stumped like this. I had a good time learning react but there are certain things in redux that don’t make sense to me at all. I need to clear my head a bit. I spent over 8 hours yesterday trying to make sense of how combineReducers works. I emerged totally confused.

So if you want to understand what combineReducers does,
you can see the actual JavaScript code here,
starting on line 440:

https://unpkg.com/browse/redux@4.0.5/dist/redux.js

I would paste it into repl.it and try it out.
I would also write a comment above every line of code and explain to yourself what the line does.

2 Likes