Javascript – Redux – multiple stores, why not

javascriptredux

As a note: I've read the docs for Redux (Baobab, too), and I've done a fair share of Googling & testing.

Why is it so strongly suggested that a Redux app have only one store?

I understand the pros/cons of a single-store setup vs a multiple store setup (There are many Q&A on SO on this subject).

IMO, this architectural decision belongs to the app developers based on their projects' needs. So why is it so strongly suggested for Redux, almost to the point of sounding mandatory (though nothing is stopping us from making multiple stores)?

EDIT: feedback after converting to single-store

After a few months working with redux on what many would consider a complex SPA, I can say that the single store structure has been a pure delight to work with.

A few points that might help others understand why single store vs many store is a moot question in many, many use-cases:

  • it's reliable: we use selectors to dig through the app state and obtain context-relevant information. We know that all the needed data
    is in a single store. It avoids all questioning as to where state
    issues could be.
  • it's fast: our store currently has close to 100 reducers, if not more. Even at that count, only a handful of reducers process data on
    any given dispatch, the others just return the previous state. The
    argument that a huge/complex store (nbr of reducers) is slow is
    pretty much moot. At least we've not seen any performance issues
    coming from there.
  • debugging friendly: while this is a most convincing argument to use redux as a whole, it also goes for single store vs multiple
    store. When building an app you're bound to have state errors in the
    process (programmer mistakes), it's normal. The PITA is when those
    errors take hours to debug. Thanks to the single store (and
    redux-logger
    ) we've never spent more than a few minutes on any given
    state issue.

a few pointers

The true challenge in building your redux store is when deciding how to structure it. Firstly, because changing structure down the road is just a major pain. Secondly, because it largely determines how you'll be using, and querying your app data for any process. There are many suggestions on how to structure a store. In our case we found the following to be ideal:

{
  apis: {     // data from various services
    api1: {},
    api2: {},
    ...
  }, 
  components: {} // UI state data for each widget, component, you name it 
  session: {} // session-specific information
}

Hopefully this feedback will help others.

EDIT 2 – helpful store tools

For those of you who have been wondering how to "easily" manage a single store, which can quickly get complex. There are a tools that help isolate the structural dependencies/logic of your store.

There is Normalizr which normalizes your data based on a schema. It then provides an interface to work with your data and fetch other parts of your data by id, much like a Dictionary.

Not knowing Normalizr at the time, I built something along the same lines. relational-json takes a schema, and returns a Table-based interface (a little like a database). The advantage of relational-json is that your data structure dynamically references other parts of your data (essentially, you can traverse your data in any direction, just like normal JS objects). It's not as mature as Normalizr, but I've been using it successfully in production for a few months now.

Best Answer

There are edge cases when you might use multiple stores (e.g. if you have performance problems with updating lists of thousands of items that are on screen at the same time many times per second). That said it's an exception and in most apps you never need more than a single store.

Why do we stress this in the docs? Because most people coming from Flux background will assume multiple stores is the solution to making update code modular. However Redux has a different solution for this: reducer composition.

Having multiple reducers that are further split into a reducer tree is how you keep updates modular in Redux. If you don't recognize this and go for multiple stores without fully understanding reducer composition first, you will miss many benefits of Redux single store architecture:

  • Using reducer composition makes it easy to implement "dependent updates" a la waitFor in Flux by writing a reducer manually calling other reducers with additional information and in a specific order.

  • With a single store, it's very easy to persist, hydrate, and read the state. Server rendering and data prefetching is trivial because there is just one data storage that needs to be filled and rehydrated on the client, and JSON can describe its contents without worrying about store's ID or name.

  • A single store makes Redux DevTools time travel features possible. It also makes community extensions like redux-undo or redux-optimist easy because they operate on the reducer level. Such "reducer enhancers" can't be written for stores.

  • A single store guarantees that the subscriptions are called only after the dispatch has been processed. That is, by the time listeners are notified, the state has been fully updated. With many stores, there are no such guarantees. This is one of the reasons Flux needs the waitFor crutch. With a single store, this is not a problem you see in the first place.

  • Above all, multiple stores are unnecessary in Redux (except for performance edge cases which you are supposed to profile first anyway). We make it an important point in the docs so you are encouraged to learn reducer composition and other Redux patterns instead of using Redux as if it was Flux, and losing its benefits.