React State vs. Redux State: When and Why?

Just about any app you write needs a way to manage state. Redux manages state and state transformations and is often used with React, but React has its own concept of state.

When using these libraries, it’s good to know which to use when. Even if you choose to use Redux in your project, you will still need to make decisions on how much of your data is stored in Redux.

The Differences

React state is stored locally within a component. When it needs to be shared with other components, it is passed down through props. In practice, this means that the top-most component in your app needing access to a mutable value will hold that value in its state. If it can be mutated by subcomponents, you must pass a callback to handle the change into subcomponents.

When using Redux, state is stored globally in the Redux store. Any component that needs access to a value may subscribe to the store and gain access to that value. Typically, this is done using container components. This centralizes all data but makes it very easy for a component to get the state it needs, without surrounding components knowing of its needs.

In You Might Not Need Redux, Redux author Dan Abromov argues that Redux is not always necessary when using React, despite the two often being used together. I would highly recommend that you read his argument before reading on here.

Assuming that your app does use Redux, you need to determine what parts of the state are stored in the Redux store, and what parts are stored in React component state. In this post, I’ll lay out a few of the factors that I use to determine where state will live.

Duration

Different pieces of state are persisted for different amounts of time. I loosely categorize time into these groups:

  • Short term: data that will change rapidly in your app
  • Medium term: data that will likely persist for a while in your app
  • Long term: data that should last between multiple visits to your site

Short-term state

I think of short-term data as data that will likely change rapidly—data that may represent only part of an atomic change to the state. At the simplest level, this includes the characters present in a text field as the user types. I would also extend this to include data in an entire form; this data can be considered a work in progress until the form is submitted.

I like to store this type of data in local React state. I would even include things like how to filter a list of items, and whether or not to show or hide completed items in a to-do app—assuming it is not tied to user preferences.

Medium-term state

By medium-term state, I mean state that will stick around while the user navigates your app. This could be data loaded from an API, or any changes that you want to be persisted up until a page refresh. After submitting a form, I would store the state in the Redux store. As an example, if a user submits a form updating their profile information, it would make sense to store this in Redux.

Long-term state

This is state that should be persisted between refreshes of the page or between separate visits to the page. Since the Redux store will be created anew when refreshing, this type of data should be stored somewhere else—likely to a database on a server or into local storage in the browser.

Breadth of Use

Another consideration is how many components in your React app need to access the state. The more state needs to be shared between different components in your app, the more benefit there is to using the Redux store. If the state feels isolated to a specific component or a small part of your app, React state may be a better option.

Depth of passing down props

React state should be stored in the most top-level component for which a subset of its subcomponents will need access to the state. Sometimes, this can mean many layers between the component storing the state and the subcomponents that render the data, and each layer means another prop must be propagated down the virtual DOM.

This works great if you only need to pass the state down one or two levels into the subcomponents, but beyond that, it can feel tedious and require edits to many components every time you find a subcomponent needs access to new state. In cases like this, I find it much easier to store the state in Redux and use a container component to pluck the desired data from the store.

Unrelated components needing the same state

It could also be that multiple, relatively unrelated components need access to the same state. Take the above example of a form to update a user’s profile. The component here should receive the initial user profile in its props. You might also have a header component with a subcomponent that displays the user’s username or related data.

You could, of course, take passing down props to the extreme, in which your top-level component knows about the user’s profile and passes it to the header, which passes it to a subcomponent (and maybe further), and also passes it down to the profile-editing component. However, this requires a lot of management between the whole virtual DOM.

This type of solution is solved much more cleanly by storing the profile in the Redux store, and allowing container components around the header and profile-editing component to grab data from Redux’s store.

Ability to Track Changes to the State

Another time to choose Redux is when you need to track changes to state. Maybe you want to replay events. Maybe you want to implement undo/redo in your app. Maybe you just want to log how state is changing.

In cases like these, Redux is a great solution; each action that is created is an artifact of how the state changes. Redux makes all these tasks simpler by centralizing them in a single store.

Wrapping It Up

There are a lot of considerations that go into where to store state in a React/Redux app. If you draw different lines on when to use them, leave me a comment.

Conversation
  • Mark Erikson says:

    Good post. Also worth noting the Redux FAQ entry on the question, at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state:

    > Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.

    > Some common rules of thumb for determing what kind of data should be put into Redux:

    > – Do other parts of the application care about this data?
    > – Do you need to be able to create further derived data based on this original data?
    > – Is the same data being used to drive multiple components?
    > – Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
    > – Do you want to cache the data (ie, use what’s in state if it’s already there instead of re-requesting it)?

  • Avi Block says:

    If you wanted to log to the extreme, to the point where everything the user did is logged (even opening down dropdown X), will that trump the other rules?

    • Tyler Hoffman Tyler Hoffman says:

      Yeah, I think in that case, I’d want to let redux handle it. That’s actually discussed in the redux docs on middleware.

  • incze says:

    I would use “centralized/singleton state/store” instead of “redux”.

    • Yago Lopez says:

      Exactly. In Angular you could define your state in a service (which is singleton by default and shared by all components) and make it reactive (Observbale) whitout all the Redux boilerplate and complexity. I would like to decide what solution is simpler. What do you think?

      • incze says:

        A word was missing in my comment: I would use the *wording* “centralized/singleton state/store” instead of just mentioning redux. It depends on your scenario, it can be a service and can be a framework like mobx or ngrx – your mileage may vary. The architectural musings of this article apply to any of them, not only to redux.

  • Erik says:

    “As an example, if a user submits a form updating their profile information, it would make sense to store this in Redux.”

    I don’t understand why React state wouldn’t be appropriate for this contrived example. I can envision a situation where the component renders a form and tracks its own state of that form in local component state.

    • Andrii Los says:

      He meant, that once you submit it, you will probably change a route, and to keep this data in React state you will need to move it very high to the godlike highest level component state (which will basically do the same thing as Redux), to keep it there and to pass it down later on if so needed. While in Redux you just dispatch one action and until page refresh happened data is here for you in every part of the app without much hassle.
      Of course, you can use Root component as Redux like thing, but for me, it doesn’t make sense since you need to pass all functions done binded to him or make them context fields to pass down to all child etc. Which is way too complex and just doesn’t scale well.

  • Jay Ng says:

    Really good post!! Clear and succinct!

  • Matthew Gagliardo says:

    Another pro to using Redux, even in small applications, is that state changes are immutable. While using Redux it is less likely to cause problems in your application due to state mutation.

  • Magnus says:

    In addition to what you wrote (thanks!) it’d be interesting to hear if you have any thoughts, about sharing state between different browser tabs,

    via a service worker?

    Sort of, keeping a Redux store in a service worker. And updating it, when a browser tab needs data. Later on, when another tab needs the same data, it’s available immediately from the Redux store in the service worker. … Does this make sense? And I suppose that each tab would have its own store too. The service worker’s store, would be just a cache.

    • Tyler Hoffman Tyler Hoffman says:

      Hey Magnus,

      What you described sounds reasonable, but unfortunately I don’t have much experience with service workers, so I’m afraid I don’t have too much to offer on that topic. After a bit of googling, I saw a few posts on using redux in a service worker, so it certainly seems doable. I’d be interested to hear if that approach work for you!

  • Khilendra S says:

    Thanks
    Its very helpful for me. Before reading your articles I was very confused. Should I use redux or not with my new projects.
    Now I will start…

  • Venkatesh says:

    Thank you.
    My question is that maintaining a large number of data items (around 100) in a component state and setting up to flatlist and then interaction with each item in flat list needs to update the whole state (means 100 items) which degrades performace as list of items increases. Can I use redux store instead of component state not to lowers the performance? Does it work?

    • Tyler Hoffman Tyler Hoffman says:

      Hey Venkatesh,

      You could definitely use redux in this case, but I doubt you’d see much difference in performance between using react state vs the redux store (if anything, I’d guess redux state would be slightly slower). I haven’t worked much on optimizing FlatLists performance, so unfortunately, I don’t have too many suggestions there.

  • Comments are closed.