August 01, 2020
Every now and then I see a tweet poll asking what we do for state management in React. In many cases the options are constrained to Redux, MobX and more recently React Context + Hooks.
Of course the only correct answer is it depends.
But here’s what I do for medium-sized CRUD-like single-page React applications.
useReducerhooks, keeping state close to where it’s used.
The application state must be kept somewhere. I can keep it hidden away in memory or I can expose it in the URL, so our users (and developers) can benefit from it.
I try to keep most of the application state in the URL, and I use React Router to handle the routes.
I cannot stress this enough. Fortunately other people can explain this better than me:
UI state should be separate from the server cache (often called “state” as well), and when you do that, you don’t need anything more than React for state management. Kent C. Dodds
Here’s an excellent article: Why You Should Be Storing Remote Data in a Cache (and Not in State) by Jason Ankers.
“Remote data is read-only. It doesn’t belong in the same location as our UI state.”
In CRUD-like web applications, where the server is authoritative, I don’t want the client-side copy of the data to become stale.
These libraries store the fetched data in a static cache; and there’s no need to resort to React Context to “share” the data with other components because all components consuming the same data are automatically rerendered when the cache changes.
At work, earlier this year we refactored one of our SPAs to use SWR and the result was a much simpler application logic. In addition, we now benefit from all the nice features that come with SWR such as “focus revalidation” and “refetch on interval”. The app has been up and running for months and we haven’t experienced any issues.
Almost everything that isn’t caught by the above cases is local UI state such as the visibility of modal dialogs or the fields in a form before it’s submitted.
For these cases I prefer to keep the state close to where it’s used. I usually find myself using
useState and occasionally