- Redux is cool but there’s so much decoupling that it gets hard to read the code. New hires would take too long to start, TS types got crazy, it was too much.
- XState is very good for state machines… but you barely ever need that level of control. Most of the time understanding it ends up being overhead. We’ve had maybe one good case for using it in about 10 years.
- React’s contexts are minimum overhead and work very well with “jump to definition” functionality and TS types. You can choose to use a reducer if you want, or skip it if it isn’t appropriate.
YMMV of course. This is just us.
Add anything you want to keep to it, store it in the window with window.app = {}
You can mix local storage in with it too if you want to write a class that checks its existence with a key.
Why must state management need a complex solution?
I’m sick of frameworks and modes where they abstract away the simplicity of javascript in favor of their way which is very economically driven.
(Been using preact/react since 2016, angular/jquery before that)
The cons are:
- A fair amount of work to make changes to the state side-effect free, but the documentation has a good tutorial on how to approach this.
- It's for ClojureScript, so it's a non-starter for organizations that will not consider anything outside of the mainstream.
I have also used Elm. If I recall correctly, Elm's state management paradigm was inspired by re-frame. I found writing JSON decoders in Elm to be demoralizing and tedious. Since the creator of the language was vehemently opposed to providing any real JSON support I decided to move to ClojureScript.
- Provided it is not an offline-first app, move as much state handling as possible out of the frontend
- use SWR or React Query for server state
- Keep pagination, filters, and other such options in your URL
- Hold state as local as possible. Only ever move state up if two or more branches of the tree need to be synchronised.
- Pass information down through props. That is what they are for. A little “prop drilling” is fine.
- Use CSS custom properties for theming
This gets you >95% of the way with very little complexity.
For the leftover pieces of global state like ‘isSidebarVisible’ I like Zustand because it is tiny both in bytes and concept.
I don’t like to use Context for state management because it litters the top-level with providers and causes unnecessary rerenders.
Avoid a single global store at all costs.
It gets out of the way in terms of boilerplate, has a good solution for avoiding unnecessary re-renders, has tooling for deep state updates without messy syntax (immer) and strikes an overall good balance between powerful and easy to use. Cons might be that it is a bit more obscure so people might have to learn it. Also the learning curve is a bit steep. YMMV
This is for commercial reasons. Apps that depend on assets are crippled over low-bandwidth or otherwise unreliable connections, and frequently break in the presence of aggressive content blockers. I won't do that to my customers.
This can scale to much greater complexity before it becomes an issue than many are willing to admit.
The app I'm building (https://inventai.xyz) is non-trivial, especially the canvas. There hasn't been any cost or downside. Quick to learn and implement.
It is simple (no need for lots of boilerplate code), reasonably performant, integrates with the browser Vue dev tools nicely and is just generally a pleasure to work with, especially because Vue does a few things better than React in my eyes - most notably, the hooks.
Pinia in particular also seems to generally get out of your way and doesn't enforce a particular architecture upon you. Want to add methods to the store to interact with an API and not have to think about that in your other components, merely call a method for initializing some data from the API that will take care of the store state? Sure! Want to do the opposite and only use the store for persisting data, regardless of where it's initialized? Go ahead. Want to have your components react to changes in the store? This will work with either approach.
This is subjective, of course, but personally that combination of tools has resulted in a pretty good development experience, in my eyes something like the following is a nice stack:
- Vue 3 with Composition API (hooks)
- using SFC with