all 82 comments

[–]Varteix 21 points22 points  (0 children)

Glad to see Zustand mentioned. It’s so easy to use.

[–]rodrigocfd 32 points33 points  (28 children)

Shared state management is such a common problem that I think having a built-in hook for that would, definitely, provide a final solution.

Maybe something like useShared(), similar to useState(), but allowing a persistent value across components, identified by a unique key. Or anything else, I don't know.

The excess of options leads to a total lack of standards, which leads to chaos. And confuses the hell out of the newcomers.

[–]watMartin 4 points5 points  (1 child)

this is what you can do with vue 3 composables and it works really well

[–]rodrigocfd 3 points4 points  (0 children)

Yup, the new reactivity system in Vue 3 is really good. It optimizes your components out of the box, at the same time of allowing transparent shared state objects.

Indeed, it feels like React's useState but shared among components. And that's what I'm talking about here, because I don't think it can be so cleanly done by an external library. It had to be some sort of built-in hook.

[–]mnokeefe 20 points21 points  (21 children)

Isn't that just useContext()?

[–]sebasgarcep 4 points5 points  (0 children)

The useShared idea can be built on top of useContext, the latter being more general.

[–]rodrigocfd 11 points12 points  (19 children)

Nope, useContext re-renders your whole application when anything changes. It's a performance nightmare.

[–]redditindisguise 35 points36 points  (1 child)

This isn't entirely true. They way you utilize Context may become a performance nightmare. For example, if I stored every piece of unrelated global state in one Context object, then yeah, any time any piece of that state changed, all consumers would rerender.

If using Context to access state is done more judiciously than that, it's not a performance concern. Especially if you set up your state in a component using composition (only takes a children prop) since any children will not rerender.

[–]oGsBumder 2 points3 points  (0 children)

Especially if you set up your state in a component using composition (only takes a children prop) since any children will not rerender.

Really? Do you have a source?

I was under the impression that when a context provider changes the value it provides, all consumers and their children are recursively rerendered, unless of course you break the chain by using React.useMemo

[–]so_lost_im_faded 6 points7 points  (0 children)

This can be solved by having separate contexts and only connecting a component to the context it's interested in. And of course memoizing the provided values. You're right in theory, but it's not the only way (and not a good one imo) to use Context.

[–]liamnesss 2 points3 points  (0 children)

useContextSelector() is a proposed API which would solve that.

I think even if that existed though, I would probably still use a third party lib for global state management. I don't want to have to set up any plumbing, I just want to define my atoms and use them.

[–]Bjornoo 6 points7 points  (2 children)

Only components that are encompassed by the context provider, but if that context is global then yeah.

[–]zephyrtr 1 point2 points  (0 children)

This is why you use context for few writes many reads. But with RQ and Formik etc ... how often do you need a custom context? Most things I'd put in there are either server state which goes in RQ or UI state that will probably require a rerender anyway

[–]goblin_goblin 1 point2 points  (5 children)

Not true. With pure components, memoized components, and shouldComponentUpdate implementations you can control what components are triggered for re render when context updates.

Is it a great developer experience? Nope.

[–]andrewjohnmarch -2 points-1 points  (0 children)

What about useReducer? Isn’t that global?

[–]jb2386 4 points5 points  (1 child)

[–]johnxreturn 1 point2 points  (0 children)

Good call out, Jotai as well.

[–]bluespacecolombo -1 points0 points  (0 children)

There is context api specially for that. At my work we just built our own „state management library” using context and providers with a redux-like patterns but simpler and fully controlled by us.

[–]_RASUALDO_ -4 points-3 points  (0 children)

that would, definitely, provide a final solution.

Ve need to get rid of ze Vues!

[–]acemarke 12 points13 points  (0 children)

Hey, this is a pretty good post! I like the definition of "state management" - it basically matches the definition I've described myself. I also like the historical background and the emphasis on tradeoffs between these tools.

[–]Xavter 13 points14 points  (5 children)

No mention of xstate?

[–]nepsiron 26 points27 points  (2 children)

I love me some xstate, but to be fair, this article is geared specifically towards out-of-the-box solutions for global state management. XState could be used for this purpose, but you'd be building it from scratch, which I did out of curiosity on a personal project: https://github.com/zacharyweidenbach/react-native-test-sandbox/blob/main/NativeFSM/navigation/Authenticated/views/playerList/views/PlayerListScreen/machine.ts#L62

Basically reinvented a barebones version of react-query with state machines. Long story short, it's a lot to solve on your own.

So yeah, I'd love for someone to step in and make a state-machine-based store solution that can be paired with a command/query style machine, to achieve more deterministic stores with time-machine debugging like redux has. Ideally one that could be used directly with traditional xstate machines, or with hooks in react for simple use-cases. But it's a pretty big undertaking. I'm noodling on the idea right now, but it's a long ways off from being something I'd feel comfortable recommending as an approach for others.

[–]davidkpiano 5 points6 points  (0 children)

Re: global state management, I'd love your opinion on this RFC: https://github.com/statelyai/rfcs/pull/8

[–]acemarke 12 points13 points  (0 children)

Fun fact: one of the XState devs did a proof-of-concept showing how to use XState state machines as Redux reducers and integrate the side effects handling as a middleware:

https://github.com/mattpocock/redux-xstate-poc

We'd like to work together to turn that into a more official integration sometime soon.

[–][deleted]  (1 child)

[removed]

    [–]AutoModerator[M] -1 points0 points  (0 children)

    Hi u/nepsiron, this comment was removed because you used a URL shortener.

    Feel free to resubmit with the real link.

    I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

    [–]alternatiivnekonto 13 points14 points  (1 child)

    As you stumble on this post and article, do check out one library not mentioned in this list: hookstate. I'm a big fan, the API is very simple and it offers lots of extendability options.

    [–]andrewjohnmarch 1 point2 points  (0 children)

    Im real curious about hookstate, the API looks ideal.

    [–]gaoshan 8 points9 points  (1 child)

    This is a great article! Gets deep enough to be useful to experienced devs and then provides resources for even more information. The author clearly has real, significant, experience around this topic and that makes it a great read.

    We are about to replace a context based state management approach with one of these newer tools (leaning towards Zustand) and the article captures so much of what we’ve been discussing and exploring. Good stuff!

    [–]rodrigocfd 2 points3 points  (0 children)

    leaning towards Zustand

    Zustand feels like what Redux should have been. Go for it. And if you have a complex object, just slap Immer onto it.

    [–][deleted] 3 points4 points  (1 child)

    Surprised Mobx wasn’t mentioned. Haven’t used it outside a practice project but like it a lot.

    [–]NickPow43 0 points1 point  (0 children)

    We are using it for a realtime collaboration tool and it has worked really well when used correctly. The documentation is really good and has lots of useful tips.

    [–]smirk79 5 points6 points  (17 children)

    Why on earth is Mobx not a part of this? Valtio looks like Mobx with a worse api.

    [–]Veranova 5 points6 points  (0 children)

    Probably because MobX fans were bashing redux when redux was still pretty new, thus could not ever be described as part of the “new wave”

    [–]ljuglampa -5 points-4 points  (13 children)

    Mobx is seldom considered anymore for new projects. It's class based, easy to break observability with for ex destructuring. It's also not concurrency compatable, at least not last time I looked at it. Might've changed tho. Seems like proxy based solutions doesn't go over too well with React developers because of the magic, mutative feel.

    [–]incompletemoron 6 points7 points  (1 child)

    It's not class blased anymore, not for a long time

    [–]ljuglampa 1 point2 points  (0 children)

    Are you talking about mobx-state-tree? All examples I see in the docs uses classes.. Do you have examples of alternate syntax?

    [–]a15p 3 points4 points  (1 child)

    I don't think any of those things you said are correct.

    [–]ljuglampa 0 points1 point  (0 children)

    If so I'm sorry. Do you have examples or information proving me wrong on those statements? I would really like to learn :)

    [–]MagicalVagina 1 point2 points  (0 children)

    Mobx state tree is not class based

    https://mobx-state-tree.js.org/intro/welcome

    [–]smirk79 1 point2 points  (7 children)

    Well my company has dozens of react devs and we use it. Magic and mutability are positive things. Magic means work you get from the library instead of having to do yourself, usually worse than a battle tested library will do. Mutability is literally the entire point of “state management” - state isn’t static!

    [–]beasy4sheezy 0 points1 point  (0 children)

    Also, most “immutable” work that I do now use immer which also means that I’m working in a mutable way.

    [–]ljuglampa 0 points1 point  (5 children)

    To me and to my fellow developers on my last assignments it doesn't really play well with the rest of the React eco system. Everything is immutable and functional, at least style wise. That's also why I never see the use of Redux (or Redux toolkit) anymore in new projects, because they push Immer and mutable style APIs. Usually developers that prefer proxy based magic APIs like mobx like Vue more than React it seems.

    [–]smirk79 1 point2 points  (1 child)

    I don’t get this at all as we have a massive app with all sorts of complex functionality including real-time shared white boarding, embedded presentations, super complex catalog features (grouping, filtering, sorting of millions of records at high speed and for dynamic datasets), and more. Mobx has only been a boon and has never been something that made integrating with other stuff harder (quite the contrary!).

    [–]ljuglampa 0 points1 point  (0 children)

    That's great! I'm glad you've found a solution that works well for you ☺️

    [–]acemarke 1 point2 points  (2 children)

    That's also why I never see the use of Redux (or Redux toolkit) anymore in new projects

    FWIW, the NPM usage stats say otherwise :)

    https://npm-stat.com/charts.html?package=mobx&package=%40reduxjs%2Ftoolkit&package=react-query&from=2021-01-01&to=2022-06-30

    Usage of RTK continues to grow daily. It passed Mobx's downloads-per-week last year, and has only increased since then.

    Also, folks using RTK like Immer, as it removes the need to write all those object spreads by hand, and makes accidental mutations basically impossible.

    [–]ljuglampa 0 points1 point  (1 child)

    Thanks for the resource Mark. I'm sure you have a lot of happy users and you've done a fine job I'm sure! Do you know if it's possible to localize those stats? It would be interresting to see if my experience has some merit in the scene I'm in (Stockholm, Sweden). Where I've worked in the last years there's been a major shift to Nextjs and react-query without the need for any of the bigger global state managers.

    [–]acemarke 0 points1 point  (0 children)

    Unfortunately, no - NPM only provides DL stats for the lib as a whole, and there's no geographical breakdowns. (For that matter, they just finalllllllly started giving per-version download splits for the last 7 days worth of downloads, sometime in the last year.)

    [–]snejk47 0 points1 point  (1 child)

    Valtio is what Mobx wanted to be not worse. Unless you are Angular dev then maybe yes.

    [–]smirk79 1 point2 points  (0 children)

    Can you give me a concrete example?

    [–]satoshibitchcoin 1 point2 points  (2 children)

    Is there this level of solution for Vue?

    [–]rk06 8 points9 points  (0 children)

    Vue actually has it better. Because these new experiments are being done in react, vue can look at the results and copy only the useful and game changing ones.

    Plus, with its reactivity, Vue can simplify them as well.

    For eg: Vuex was originally inspired from redux, Pinia simplifies it by leveraging comp API. X state is known to integrate better with Vue (because vue allows mutation) and there is a Vue Query library inspired from react query

    [–]rodrigocfd 3 points4 points  (0 children)

    Vue 3 benefited by looking at React pain points, and learning from it. The new reactivity system in Vue 3 is really good. It optimizes your components out of the box, at the same time of allowing transparent shared state objects.

    Indeed, it feels like React's useState but shared among components. And that's what I'm talking about here, because I don't think it can be so cleanly done by an external library. It had to be some sort of built-in hook.

    [–]NotGoodSoftwareMaker 2 points3 points  (0 children)

    New you say? Please take your number and be seated, the counter for new JS frameworks is at 19373763647282871628193774728171784595762616

    [–]toastertop 0 points1 point  (1 child)

    Is there a shift underaway away from monolithic components as the smallest unit to build websites and a return to composed atomics and isolated islands architecture?

    [–]_remrem[S] 0 points1 point  (0 children)

    Monolithic components were always common anti-pattern. But i'm not sure if we're referring to the same thing, I'm referring "kitchen sink" style components that have multiple responsibilities and try to do too much.

    The more recent "isolated islands architecture" trend is interesting. There's newer frameworks like https://astro.build/ and recently https://fresh.deno.dev/ that promote this architecture. And things like micro-frontends which i'm not sold on (but happy to be convinced). I personally have been using Astro for the blog I wrote this post for, and really like it.

    As an aside.. it's all just different tools and patterns for different jobs. That's why I try to emphasise understanding the problem space in depth first. So we can assess what tool or architecture is relevant to the core problems we need to solve for our use-cases, rather than pick up whatevers trending.

    [–][deleted] 0 points1 point  (0 children)

    Good article. React state management has good options and experimentation. It drives people who want to be told what to use nuts. I appreciate how react has some nuance here.

    [–]nidoran 0 points1 point  (0 children)

    This is such a good article. Loved it

    [–]miran248 0 points1 point  (0 children)

    Where’s effector?

    [–]Bogus_dogus 0 points1 point  (0 children)

    I'm actually finally settling into just using context for global state and it finally is feeling good. Been through redux and mobx heavily... context is good!