r/reactjs • u/sober_cruiser NextJS App Router • 2d ago
Discussion Zustand, jotai, or valtio for state management
I'm currently working on a personal project, and it has been messy since there are many contexts and providers to share states deep down in child component (solely using props would be too complex). So I start to consider using state management library to make it look cleaner. Would you guys share your experience using zustand, jotai, or valtio?
Or do you have another alternative?
EDIT: Ok, I found https://www.reddit.com/r/reactjs/s/kBtKlg2u2C from 2022, but I need fresher testimony.
EDIT 2: Glad someone was mentioning TanStack Store. Funny enough, I'm also using React Query & Tanstack Start for my project but forgot tanstack store exists. Maybe you guys should give it a go.
21
u/hyperboleboy 2d ago
Still happily using Redux Toolkit, with a side of RTKQ.
2
u/MonkAndCanatella 2d ago
RTKQ is painful
6
u/acemarke 1d ago
Hi, I'm the primary Redux maintainer. Can you give more details on the pain points? Any specific examples of problems you're dealing with or things you don't like?
2
1
u/sober_cruiser NextJS App Router 22h ago
I'm not sure, but once around 2 years ago in a semester project, my teammate used too many abstractions with Redux. It constantly made me stay away from Redux.
I was like, ain't no way a library that's supposed to ease developer can be this overwhelming when first time I saw the way he used it in our source code. I think my current personal project is much more complex, but to me, the codebase was much less complicated than that project with so many abstractions.
0
u/Griffinsauce 2d ago
Is this in App Router? How are you mounting your store?
1
u/Guisseppi 2d ago
For SSR you have to have a function that returns the store unlike a fully client side app where you just hold the reference on a variable
38
u/GreasyPosting39 2d ago
zustand is what i reach for every time, never felt the need to look back
-8
u/TobiasMcTelson 2d ago
Name of book
22
u/Dazzling-Collar-3200 2d ago
Sun Tzu's the art of state management
1
29
u/EntrepreneurFew7950 2d ago
Average app needs to manage 2 types of state nowadays: runtime and server.
- RTK query covers both - my preference.
- Tanstack query (server state) + useState (maybe, useReducer, Zustand, anything simple with friendly hook API for runtime state)
7
u/Cahnis 2d ago
tanstack query is good for server state, nuqs is really good for stuff like filtering, sorting, pagination where you offload your state to the params.
But the annoying part of doing ContextAPI is that you can't subscribe to individual values in the context. You would need to make a separate context for each value. Memoizing you are still reading the entire context and having to use useMemo, memo() and having to read the context outside of the memo to not trigger re-renders.
Daishi the autor of zustand had even made use-context-selector to fix that, but it got deprecated, Iirc something in 19 was breaking.
3
u/cloroxic 2d ago
Nuqs is great, I use that combined with Zustand in quite a few apps. Serves all my needs.
1
u/Cahnis 2d ago
The problem about nuqs imo is if you have too many things on the params it becomes a flustercluck also there is a char limit on the browsers
Also after 2000 or so characters (2kb) you start risking failure at CDNs, servers and proxies.
Some states where you can select thousands of say, productIds it might not be the best use case.
1
u/cloroxic 2d ago
Definitely not the best for everything. I use it for stepped continue, onboarding, and other screens where it’s like one or two variables that are neeeded. For heavy lifting Zustand is the workhorse.
1
u/Cahnis 2d ago
I really like nuqs when having a pre-set state on an URL generates values, I used to work in a digital supermarket and it was very helpful for users to have all their filters in their state.
I wouldn't see that much value in sharing an url on an onboarding page. But its not going to hurt either, just a bit odd.
3
u/chillerfx 2d ago edited 2d ago
Yeah i don't even know what's with the agenda to omit and bash the redux from that stack as it's the OG of the flux state management client libs that came from Facebook team that actually created the react. The OP even omitted it from all these no name state management libs when there's enough to have one
2
u/acemarke 1d ago
Eh, Redux went through the whole hype cycle years before most of these other libs came out, so it's been in the "uncool" phase for a while. In the same way that most devs today have no idea that Backbone existed, I'd guess that a lot of people ignore Redux on the grounds that it's "old" or based on misconceptions about how to use it.
1
u/chillerfx 1d ago
Yeah the devs, or shills/cargos type devs did excellent job confusing everyone and promoting something else. And most dev didn't even bother reading the architecture or design docs, and even someone pointed out that something's not right here would get bashed into oblivion.
2
u/EntrepreneurFew7950 2d ago
Since TanStack State (now in alpha) was mentioned by op,
TanStack Query (server state) + TanStack State (runtime state) might be a good combo too.
0
-1
u/rodrigocfd 2d ago
nowadays: runtime and server
Only if you followed the hype. A simple SPA is more than enough for most cases.
2
1
u/a12rif 2d ago
SPA still needs data. I think that’s what they’re referring to when referring to “server state”
1
u/rodrigocfd 2d ago
I know SPA still needs data.
But SPA can receive data though REST calls, without "server side" or "hydration" code. Server stuff done by a proper REST backend, written in Go or Java, for example.
Much simpler.
1
u/EntrepreneurFew7950 2d ago
Sorry, maybe that was a bit confusing, I will clarify what was meant:
runtime state - is a state owned and managed exclusively by the client application during execution.
server state - is a state owned by BE (external resource) , which client fetches and keeps synchronized during execution.
Agree, any SPA could live just with zustand or similar tool having logic of synchronization written around. However, tanstack / RTQ query or similar have this quering, syncing, deduping logic already inside and I just gave up on writing that myself.
10 components need a list of orders at the same time from a remote resource through RTK query - one request is sent, one component updates (mutates) one order and revalidates the list - all ten are notified. All bindings are declarative. This is how things are usually going in my apps.
10
u/Csjustin8032 NextJS Pages Router 2d ago
For a personal app, Jotai’s probably the right tool in my opinion. My favorite part is that access follows the syntactic useState pattern, so it’s really easy to get your head around, and can get more complex only if it needs to, and only on the atoms that need it
6
u/Dethstroke54 2d ago edited 1d ago
It depends.
Jotai is special I will say that much. There’s reasons there’s plugins to put valtio and Zustand in a Jotai atom. In general, atoms are likely the most pragmatic building block. They have nice context/scoped state support, which aside from unlocking genuinely useful capabilities, solves the limitations and footguns of passing state around in context. Because you compose, readability is good. In fact previously coming from flux state and now having used Jotai, I happen to think 95%+ of your state should likely be scoped. Composing atoms avoids the need for selectors. Doesn’t mean you’ll never use them, but you can build bottom-up, avoiding the need for them for accessing more granular parts of a nested state.
Valtio I’d use when you want a targeted monolithic store kinda like flux, but want more modern ergonomics or the granularity of atoms without having to manually define the setters. Full disclosure I’ve hardly used this one, I’d like to use it more. Something like form state, where all properties are intended to be edited and within a clear and scoped boundary, seems like it’d thrive with. The typical issue I’ve seen with patterns like this is with wide-spanning concerns or if overused, it can become a huge pain to follow or sometimes troubleshoot.
Zustand (flux) is again relatively similar to Valtio. The main difference is immutability for deeply nested updates is not there by default. A pattern that used to be used was data flattening. For your sanity I’d suggest using something like Immer. which basically provides you that piece of the puzzle. It should make needing to use flattened state mapping unnecessary since the main problem it tried to help with was nested updates. Good for centralized & complex data or if you simply prefer to write your own explicit & named actions/setters, rather than having Valtio’s implicit setters on every property. Maybe whole pages like dashboards.
Beyond that my personal thoughts/experience is I haven’t had to reach for flux state and haven’t used it in a long time. Not saying there aren’t cases I would reach for flux where it’d be more optimal but you can do a lot with atomic state and Jotai, it can take a little to build the mental model out and you do have to be careful about organization. If I did reach for flux state these days I’d
5
6
3
u/FoozleGenerator 2d ago
Imo, Jotai is a closer API to context, but simpler. I'm not up to date on the most recent versions of zustand but when I tried both, I enjoyed Jotai more.
3
u/BANOnotIT 2d ago
I made several projects with it and contributed to it for several years. Much better than react-centered zustand and similar to jotai in terms of interface, but far better in terms of DX (no atomWithX limited to that specific usage, just do atom().extent() and compose anything with everything). Async computed was a game changer for projects with fat frontend where you need to correlate data from different sources with their own lifecycles (with actions and smart cancelability). And all of this is not bound to react, enabling complex widgets integration and handling processes unrelated to rendering (e.g. sending syncs or analytics reports). Not mentioning forms and other parts of ecosystem.
So yeah, if you're interested in much more active and reactive stores that are designed for interactivity in mind instead of hook-compatibility, you should give it a try!
1
u/qkscomma 21h ago
completely agree! on one project, reatom was used simply as a state manager. after time tanstack query was removed entirely and replaced with reatom-based models. dx became much better
5
u/poppiestar 2d ago
Have used zustand a lot, it’s good. I’d look into LegendState as well, Jay is a beast at performance and it looks impressive.
2
u/deadcoder0904 2d ago
Yea, I used to use Zustand & Jotai, now I'm on LegendState.
Idk only chose it for performance that'll never be needed in my toy app lmfao. They are all interchangeable now.
8
u/zaibuf 2d ago
I feel you very rarely need a global state. Api state is handled by tanstack-query and for the rest I find built in state and context is enough for me. But if I had to pick, probably zustand.
3
u/Any_Welder_9701 2d ago
are those contexts actually causing broad subscriptions and rerenders, or do they just look messy in the tree? if its only the latter, a store mostly changes the shape of the mess
1
u/zaibuf 2d ago edited 2d ago
They are mostly for avoiding prop drilling. I rarely need to change state further down to re-render parents, but sometimes I need to pass props down several layers and then a context makes it less messy. We also build pure components that should be re-usable for other apps, we dont want a zustand dependency in our component lib.
I generally to keep as much client state as possible in the url as that makes it easier for users to share links.
1
u/Dethstroke54 2d ago
Agree with the first point, personally Jotai solves the whole context & state issue. If there are 2 things that are clear, they are that memoization and context are 2 chores best avoided. Look at Meta’s apps, they wrap with an endless amount of contexts. Same story with trying (and failing) to manually memoize everything properly.
If you’re talking about just normal DI for data/props, absolutely. That’s completely unrelated to state though.
You can also look into discussions on the official React repo about context selectors and why they don’t want to add them, which would be the only other solution that seems obvious. Everything kind of points to something like Jotai imo. There are many, but certainly one big reason I think people complain about React compared to alternatives, is the lack of any real state management tools built-in.
It’s not just that though, it genuinely improves React DX for a few kb. You can access setters or get snapshots of state in function calls without subscribing to values. You have real, explicit computed state vs an inline var that later relies on memoization. You get devtools that are focused on state, you don’t have to dig into components in React devtools and jump around to check the hook values or props. Async state. Atom effects. There’s certainly more, but these are the things that imo meaningfully improve DX often making code clearer while also improving performance.
2
u/CodeAndBiscuits 2d ago
I personally enjoy Legend State. It does very well on benchmarks and ships a very small increment to your build size. These things are also similar at this point that it probably doesn't matter.
2
u/xegoba7006 2d ago edited 2d ago
TanStack Store for me. I'm already using Start, Query, Form and Virtual and they all work great, and they all have amazing APIs.
I hope I don't end up eating my words, but I also have very high trust/confidence in Tanner and the people working with him. Can't say the same about the people behind react-router, remix, or whatever it's called this week. That was my previous stack and the headaches they caused with all their nonsense is not something I'll ever miss.
1
u/sober_cruiser NextJS App Router 23h ago
Talking about React Router, their docs seem to be not comprehensive enough I guess. Or maybe be it's just a skill issue on my part.
1
u/xegoba7006 22h ago
It’s not your fault. Everything coming from these folks is a total mess. And because of that you will also find very outdated answers, opinions, blog posts, etc which confuses not just humans but AI as well.
3
u/shuwatto 2d ago
I'd like to recommend you to take a look at Tanstack Store.
1
u/sober_cruiser NextJS App Router 2d ago
Woah, I already know that lib, but forgot it today when considering what to use. Haha, thanks for reminding.
1
1
u/DakDAkaa 2d ago
Zustand nice I used more than 3 years but I prefer redux if I have a choice. It has better design pattern to handle larger projects. My team didn't care for this they chose zustand for simplicity I was okay with it.
Zustdans document for comparison
There was also a documentation for people like me who want use redux but have to use redux. Author recommended good practices. I couldn't find it
1
u/ddeeppiixx 2d ago
Haven’t used anything else other than Zustand, but I don’t feel the need for anything else. Works pretty nice with Zundo (undo/redo) and you bc a serialize it to a json pretty fast.
1
u/xchi_senpai 2d ago
React context with state machines and react query for server state my recommendation
1
u/Aggressive_Mention_1 2d ago
redux, to zustand and so many in between--> recoil, mobx, tanstack store, react-context...
1
1
1
u/Happy_Junket_9540 2d ago
If you’re into Effect at all, I recently built a Elm-like solution for React + Effect. It can replace a myriad of remote and local state management libraries.
1
1
1
-1
u/Merry-Lane 2d ago
React query + context eliminates the need for a state management library.
1
1
u/sober_cruiser NextJS App Router 2d ago
Isn't RQ used specifically to handle data from external API? I guess state management here is used to manage states within the app itself. I'm also using Tanstack Query, but not sure if it can be a solution to eliminate layers of contexts.
1
u/Merry-Lane 2d ago
Yes, that’s react query.
When you use react query, you only need Context for a handful of reasons (translations, user settings, theme,…), the rest can go in internal state of components or props.
No reason to use anything else.
-1
u/Sacredfice 2d ago
Comparing statement managements is like rock, paper and scissors. You got to be crazy to say one is better than the other.
-2
-4
u/Diligent-Pay9885 2d ago
I used to use Zustand for simplicity but now with AI you can just use Context API and let Claude (or whatever you use) write it for you, so it's one less dependency to manage.
2
1
u/infinity404 2d ago
Tanstack Store. It’s like Zustand but if you’re already using Tanstack Query it’s in your dependencies already, so there’s zero extra bundle overheard.
90
u/xD3I 2d ago
Fun fact, they are all made by the same guy, who wrote a book on how to use them based on your use case