At the beginning of the year if you told me I’d be publishing a recommendation to use Redux I would have laughed in your face. Yet here we are.
State
State is persisted information that determines how an app will be rendered.
We will be discussing the following types of state:
Local State: Refers to state persisted within a React Component. Global State: Refers to state persisted within a global store that all components have access to. Server State: Refers to state persisted on a server. (and for the sake of this conversation — automatically managed in client cache, using a tool like React Query.)
Redux
Redux was created in 2015 by Dan Abramov and Andrew Clark as a solution for managing and providing state across an entire React application. Redux creates a Global State named a Store, and allows you to connect Components to the Store to gain access to the Global State. Redux helps prevent prop drilling and makes managing state across many components much easier.
But classic Redux comes with many pain points including:
- A steep learning curve
- A notorious boilerplate problem
- Lack of a standard architecture — no 2 Redux implementations were the same; few were good
- Poor TypeScript support
Redux Toolkit
In October of 2019 Redux Toolkit 1.0 was released.
“Redux Toolkit is our official, opinionated, batteries-included toolset for efficient Redux development. It is intended to be the standard way to write Redux logic, and we strongly recommend that you use it.”— Redux Team.
Mark Erikson’s vision for RTK aimed to solve the aforementioned problems, and ultimately succeeded.
The 2 big features that make RTK worthwhile in my eyes are createSlice, and the opinionated Style Guide.
A slice is where you define the state of a feature, which ultimately gets passed to combineReducers when configuring your store.
import { createSlice } from '@reduxjs/toolkit';
const initialState: {
mode: 'light' | 'dark';
} = {
mode: 'light',
};
export const themeSlice = createSlice({
name: 'theme',
initialState,
reducers: {
toggleThemeMode: (state) => {
state.mode = state.mode === 'light' ? 'dark' : 'light';
},
},
});
export const { toggleThemeMode } = themeSlice.actions;
export default themeSlice.reducer;
But even with RTK, I still wasn’t sold. That is in large part because around the time RTK was released, so were the Server State tools.
Server State Tools
In 2019 SWR & React Query were introduced to the React community. SWR created by Vercel, and React Query created by Tanner Linsley, both solve the same problem: fetching, caching, synchronizing, and updating Server State. Server State aims to keep the single-source-of-truth on the server, likely persisted in a database, and remove the need for maintaining and synchronizing server derived state with Global State.
Because of the little Global State that remains when abstracting Server State to a query tool, there is little reason to use Redux. The remaining Global State, if any, could easily be managed with the Context. At this moment in time, I was a strong advocate for avoiding Redux, in favour of a Server State tool + Context. But then RTK responded.
RTK Query
In June 2021 Redux Toolkit added a very powerful tool that makes Redux a more viable solution: RTK Query.
Similar to SWR & React Query, RTK Query is a data fetching and caching tool that manages Server State.
One big benefit of using RTKQ is that it integrates with your Redux Store. Every interaction with RTKQ dispatches a Redux Action. This allows every interaction to be visible by all Redux Reducers, and even the Redux DevTools. This can be incredibly powerful for any tool that integrates with Redux, like Sentry.
So now that RTK has a Server State solution, the deciding factor comes down to how you want to manage the remaining Global State in your app. At this point, you can either create a Redux Slice, or use Context. Both solutions are roughly the same amount of boilerplate. Redux does however have some benefits.
The first is out-of-the-box performance. If you’ve ever read any article about Context, you’ll know it’s often discouraged as a state management solution. That’s because it’s very easy to build performance problems into your app if you’re not utilizing Context correctly.
The second is the idea of having a single Provider — as opposed to using Context where you’ll need a Provider for each feature, all of which could appear anywhere in your component tree.
Conclusion
I can’t believe I’m saying this, but I like Redux now. Thanks to Redux Toolkit and the newly released RTK Query, implementing Redux is actually very pleasant, and you gain a lot by using it, especially in an enterprise environment.