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.
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.
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
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.
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.
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.