Are you building or planning to build a React application, and need some way to handle your state? Then you are spoiled for choice. The state management scene might have been calming down after its initial explosion in 2014, but there are still plenty of both stable and cutting edge alternatives to look into.
Redux has been the market leader for years now, but thanks to developments in both React itself and competing technologies, there might be better choices available.
This article will introduce you to a variety of different approaches that will enable you to write maintainable, testable and understandable applications in no time.
#1: Just use React
Before we start discussing the slew of alternatives waiting to handle your state, I think there’s one hot potato that just needs to be put out there. React ships with all the features you need to handle all your state without a single library to help you out.
When Redux was at the top of its game, lots of teams placed Every. Single. Piece. Of. State. in Redux. What dropdowns were open, what page you were on, and even what you had typed into your form fields. In retrospect, this was a pretty bad approach. Even if the idea of centralizing all state in a single place sounds tantalizing (the Elm architecture does this, for instance), it often feels over-engineered for most use cases.
Because most state doesn’t need to be global. Most state lives just fine in a
useReducer or custom hook next to your components. You can prop-drill for a component layer or two, or you can create custom contexts to save you the trouble. There are some use cases this won’t work due to performance constraints, but those are few and far between.
So before you dive into the world of advanced state management, consider using the tools React ships with out of the box.
#2: Just use React + SWR || React-Query
Back when I started using Redux, most of what I wanted to do was to share state across my apps. Data I had fetched once, and didn’t want to fetch again for a while. Redux and their thunks gave me that in a pretty easy way - but there were a lot of boilerplate you had to work around
Most of the data you need to share across your application falls into two categories. Server cache, and global state. Server cache, or data you have to request from the server, store in some kind of state management device, and fetch again later on, can be separated from global state, in that it’s not user generated in the same way.
Today, there are several libraries that help you with server caches. React Query is the most popular alternative, and SWR is my personal favorite. Both of these options follow a very similar API, caches your server requests, and provide smart defaults for refetching that data in the background. You can customize everything to your own requirements, and share secrets like OAuth tokens between requests. Oh, and loading- and error states are either indicated through boolean flags or handled through suspense and error boundaries (if you run a React version that support those, that is).
By using one of these libraries to handle all server state, you can handle any non-server-related state with contexts or local state - and in most cases, there isn’t a lot of state left to handle.
#3: Redux Toolkit
Lots of people are really invested in using Redux, and it’s not without reason. Redux comes with great developer tooling, a solid one-way data flow, and great documentation. So is there a way to continue benefiting from your existing knowledge and toolchain without all the boilerplate and indirection of bare-bones Redux?
RTK - or Redux Toolkit - is an opinionated library that makes working with Redux code much easier and less boilerplate-y. It uses conventions to simplify reducers, async communication and store creation, and the
[immer](https://immerjs.github.io/immer/) library makes changing the state a breeze.
RTK really rejuvenated the Redux community, and is actively maintained by the maintainers of Redux. If you’re sold on The Redux Way™ - this is definitely the best way to implement it in 2021.
Recoil is a new state management offering from Facebook, and is still being developed actively. It is developed specifically for React, and makes creating shared state a breeze.
Each piece of shared state is called an atom, and atoms can be combined with selectors that only recompute whenever an atom changes. Asynchronicity is built in, so any state update can be dependent on server communication or stuff happening in web workers. And you can structure your atoms in any data structure you want (trees, graphs, you name it). In other words - Recoil is powerful!
The documentation is great, and the API is starting to become really stable. If you require really performant shared state in your application, this is definitely a great tool to reach for.
Measuring front-end performance
Monitoring the performance of a web application in production may be challenging and time-consuming. OpenReplay is the first open-source frontend monitoring tool that replays everything your users do and shows how your app behaves for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder.
OpenReplay lets you reproduce issues, aggregate JS errors and monitor your app’s performance. We offer plugins for capturing the state of your Redux or VueX store and for inspecting Fetch requests and GraphQL queries.
Happy debugging, for modern frontend teams - Start monitoring your web app for free.
Managing your state is hard, and there are tons of other competitors trying to solve the same problems. Here are two more options if you want to explore some other ways to manage your React state.
MobX has been around for ages, and is the preferred state management solution for thousands of development teams around the world. MobX’s approach to state management is making all state “observable”. You can read more about their approach in their documentation.
Overmind is another new approach to state management, which makes it easy to orchestrate rather complex state mutations. One of my favorite online tools - CodeSandbox - uses Overmind, and has nothing but great things to say about it. If you have really complex state management needs, Overmind might be for you.
Choosing how to handle the state of your React applications is one of the most important decisions you will make. Do you want to use what React ships with, do you want to use tried and tested libraries on top, or do you want something cutting edge that seems to work great right now?
As the developer making this decision, you need to consider who is going to work on your code, their competency level, the complexity of your domain and what you’re trying to build. Consider switching costs and what kind of lock-in you’re agreeing to, as well.
Personally, I tend to opt for React’s state management tools with SWR on top. I’ve been working with Recoil for a few months, and I like that approach as well. Whatever you choose, make sure you’re comfortable with it.
Best of luck!