[HN Gopher] Ask HN: What is your favorite front end state manage...
       ___________________________________________________________________
        
       Ask HN: What is your favorite front end state management solution?
        
       Did you already build nontrivial applications with it? Where does
       it shine? What are the cons? What did you try before, which didn't
       work for you?
        
       Author : manx
       Score  : 30 points
       Date   : 2022-12-25 20:12 UTC (2 hours ago)
        
       | gabereiser wrote:
       | Good ol' {}
       | 
       | 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.
        
         | Ambolia wrote:
         | I assume the idea is for changes in the data to trigger changes
         | in the UI? If you just keep the raw data on an object you still
         | need an additional mechanism to synchronize the data on the
         | screen.
        
           | whycombagator wrote:
           | That assumes the rendering is done on the front end.
           | 
           | However, you could attach event handlers for state change
           | monitoring & propagation.
           | 
           | I'm curious to know how scalable an object GP described would
           | be for UI state (assuming it needs monitoring & propagating)
        
           | swagasaurus-rex wrote:
           | Encapsulate it into two functions:
           | 
           | window.getState(); window.setState();
           | 
           | You could even use document.querySelectorAll() to go through
           | all the elements on your page, and update them based off
           | values in the state, whenever window.setState() is called.
           | This is basically all front-end frameworks in a nutshell.
           | You've invented reactive programming in the browser.
        
             | tomduncalf wrote:
             | Perhaps my way of thinking is React-centric but this feels
             | like a pretty inefficient way to do it. Feels a bit like
             | reinventing the wheel poorly when things like MobX exist,
             | sure it's simple to start off but then you hit performance
             | issues or issues with dependent state etc. etc. and you
             | realise why, for all the derision they sometimes get,
             | libraries exist to solve this problem and they are useful.
             | 
             | But for a simple thing built with JS that isn't going to
             | need to scale to a large codebase or whatever, sure, keep
             | it simple!
        
               | Kiro wrote:
               | I build games where I run a global setState on the root
               | component 60 times a second and even with deeply nested
               | components it's not even a factor in performance.
        
             | whycombagator wrote:
             | That is one way to do it, albeit a seemingly naive way. I
             | can't imagine the entire page is linearly searched to
             | update a UI element these days. Perhaps an entire component
             | in some frameworks?
             | 
             | I don't know and can't easily find out the time complexity
             | of things like React setState(), but would hope that for
             | frontend code bases where there is a build step(s) and/or
             | for typed frontend languages we could achieve better than
             | linear (especially if N is every element on the page)
        
             | sibeliuss wrote:
             | Unfortunately, it's not so simple!
             | 
             | For anything non-trivial you'd have to add some kind of
             | listener or tag to every node, find said node, and then
             | update (ideally in a performative way). Said updates cannot
             | destroy existing state, but must patch it. Updates must
             | also not break existing attached event listeners. The list
             | goes on and on.
        
       | Tade0 wrote:
       | xState
       | 
       | Sometimes you really need a state machine and for me this is the
       | go to library.
       | 
       | Pros:
       | 
       | -Visualizer. Non-tech people love the visualizer. Tech people as
       | well really.
       | 
       | -Integrates easily with entities which are also implicitly state
       | machines, like Promise.
       | 
       | Cons:
       | 
       | -Learning curve. I've already rewritten our state machine once
       | because my original implementation was not idiomatic.
       | 
       | Mobx also works. Ngrx, Redux and the like just smear your logic
       | all over the place, which is bad.
        
       | peterhunt wrote:
       | When you refer to frontend state management, I'm assuming you're
       | talking about libraries like Redux, and are using something like
       | React. Basically, storing state that cuts across the component
       | hierarchy.
       | 
       | First of all, I would suggest minimizing it as much as possible!
       | You can often get away with a combination of component local
       | state and data fetching libraries like SWR (the one I use) and
       | react-query (I've heard it's good but haven't used). Modern data
       | fetching libraries support intelligent caching, cache
       | invalidation, and even optimistic updates.
       | 
       | The vast majority of internal tools at Twitter (prev employer
       | where we built internal tools) didn't need any state management
       | at all outside of swr and component local state.
       | 
       | However there will be some cases where some sort of client side
       | state management will be useful. In these cases I reach for
       | jotai. It was one of the first state management solutions
       | designed post React Hooks, so it feels much more natural than
       | state management solutions where hooks were bolted on.
       | Additionally, it doesn't suffer from some of the rough edges that
       | similar libraries like Recoil have (like naming fatigue from all
       | those string keys).
       | 
       | Btw, I only use a tiny subset of jotai. I don't use any of the
       | persistence or async stuff.
       | 
       | So tl;dr:
       | 
       | 1. Build your app with component local state and SWR only.
       | 
       | 2. If this gets messy, refactor your component local state and
       | SWR code to be abstracted away as reusable functions / hooks.
       | 
       | 3. Only when there is a performance problem _or_ a really
       | convoluted component hierarchy that doesn 't make much logical
       | sense, consider adopting jotai, but only for the parts of your
       | app state that are causing the issues.
        
       | jahewson wrote:
       | My personal favourite is Zustand. But if you like proxy state
       | then Valtio is really nice.
        
       | h3rsko wrote:
       | Jotai [1] is my go to, though I have never used it for anything
       | too big.
       | 
       | [1] https://jotai.org/
        
       | nathants wrote:
       | reagent. reacting to deeply nested maps of immutable data in a
       | single location. this is the way.
        
       | 7sigma wrote:
       | More like a cache for back end data but it covers a lot of the
       | use cases for front end state management.
       | 
       | https://tanstack.com/query/v4
        
       | JayStavis wrote:
       | react-hooks-global-state which at this point is really just
       | Zustand
        
       | david_p wrote:
       | we're using ngrx.
       | 
       | Context: the app in a large enterprise Angular app (100+kLOC)
        
       | tuzemec wrote:
       | Trying Zustand for a mid-sized react project. So far pretty happy
       | with it.
        
       | Kiro wrote:
       | Just use a global object and continuously run setState on the
       | root component inside a requestAnimationFrame. Whenever you need
       | to use or display something just reference or set the global
       | object and you will be sure it's visually updated within the next
       | rAF.
        
       | have_faith wrote:
       | React specific but i've built a couple non-trivial applications
       | with Recoil. I enjoy the ergonomics of it and building up a state
       | graph. At its simplest it like a global version of useState which
       | is really all you need, something you're used to but happens to
       | be shared. I prefer things that have simple primitives that can
       | be composed into something complex. The documentation is good for
       | describing what it does but not the best at easing you into it's
       | mental model.
        
       | Glench wrote:
       | Svelte with stores: https://svelte.dev/tutorial/writable-stores
        
       | inopinatus wrote:
       | Assuming you mean a web-based application, then all state via
       | HATEOAS, and CSS or JS in the front-end is strictly a non-
       | essential progressive enhancement.
       | 
       | 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.
        
       | pookeh wrote:
       | Mobx
        
       | ulshv wrote:
       | Mobx. Never looking back to any other React state management
       | library
        
       | tomduncalf wrote:
       | It was always MobX for me, I've built a few sites and React
       | Native apps with it and found it extremely productive in exchange
       | for some magic, but it could be seen as somewhat heavyweight
       | compared to some more "modern" solutions. Jotai and Zustand are
       | two that I want to investigate but not used them yet.
        
       | moklick wrote:
       | I think it depends if you are working on an app or on a library.
       | In an app I would recommend to use Zustand or Jotai. If you
       | prefer a Redux-like state management with a central store and
       | actions to update it, go with Zustand, if you prefer a proxy-
       | based atomic solution, go with Jotai. There might be situations
       | in library code where it's useful to use React context but I
       | would not use it in app code. It's too easy to use it wrong.
        
       | frompdx wrote:
       | My personal favorite is re-frame for ClojureScript. I have used
       | it to build things like a LaTeX editor with live preview,
       | electron app frontends, and web-apps. There are wrappers like
       | Kee-frame that extend re-frame by linking the URLs query to the
       | current state, making it possible for users to easily share URLs
       | to different states of a single page app.
       | 
       | 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.
        
       | wotamRobin wrote:
       | Principal eng working with 3 teams on a ~500k loc React site
       | here. After lots of experimentation, we're just using React
       | contexts.
       | 
       | - 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.
        
         | sircastor wrote:
         | I came into a fairly complex app using redux. I asked the
         | developer about why contexts wouldn't be a better fit, and
         | within a week we'd dropped redux for contexts. There are
         | certainly uses where Redux really is the right tool, but it's
         | nice how flexible the built in stuff is.
        
         | Aeolun wrote:
         | What do you do for modifying the data that is shared across the
         | app? It seems like you'd either have one huge context that's
         | very hard to manipulate, or many deeply nested small ones?
         | 
         | We're using redux (with a copious amount of selectors) and it's
         | the only reason I have a little bit of confidence where all our
         | data is.
        
           | arnorhs wrote:
           | I have built a lot of apps, including huge react apps. The
           | problem you are describing is usually a result of people
           | representing too much in state of as part of the same state.
           | 
           | Now I could be wetting but it's hard to have these sorts of
           | discussions on the abstract.
           | 
           | Can you name examples of such state?
        
         | chaimsalzer wrote:
         | No issues with needless rerenders?
        
         | shukantpal wrote:
         | What are your thoughts on MobX?
        
           | aidos wrote:
           | We use mobx and I think it's great. The observable / computed
           | model is really familiar from spreadsheets so it's very easy
           | to reason about code and computations. You always just think
           | about your data in terms of being computed from dependencies
           | without worrying about pushing state though the system.
           | 
           | We have an object graph (updated via web socket
           | subscriptions) and then twist and turn slices of that data on
           | the way up to the components. I hardly think about the fact
           | that mobx is there and instead just think in terms of
           | reshaping data for display.
        
           | ledauphin wrote:
           | i like mobx because it encourages you to separate state from
           | presentation more than React Context does, but doesn't
           | discourage keeping logically separate state trees separate
           | the way Redux does.
        
       | blktiger wrote:
       | Thus far I've really enjoyed https://xstate.js.org/. It's
       | fantastic for ensuring that your application is in an expected
       | state and to control transitions between states. When it's
       | overkill you can often just drop to useState for simple stuff.
        
       | Veuxdo wrote:
       | I use the _let_ keyword to store values that I know will change.
        
       | zenosmosis wrote:
       | I prefer sticking w/ the basics and using EventEmitter.
       | 
       | https://speaker.app has a UI I've been prototyping w/ this
       | approach.
        
         | manx wrote:
         | What is EventEmitter?
        
       | revskill wrote:
       | Redux Toolkit with Typescript is my choice for now.
        
       | devmunchies wrote:
       | Been building in HTMX for the last month and I'm loving the new
       | paradigm. This vid did a good job of explaining the shift.
       | https://youtu.be/LRrrxQXWdhI
       | 
       | (Been using preact/react since 2016, angular/jquery before that)
        
         | primitivesuave wrote:
         | Thanks for sharing this, I found this paradigm to be highly
         | intuitive. Adding a link to the HTMX docs which also do a great
         | job of explaining: https://htmx.org/
        
       | fatih-erikli wrote:
       | separate useState's for each piece of a global state, preserving
       | it in a flat shape, no nested objects.
        
       | brundolf wrote:
       | I try to stick with plain React hooks when I can. For small-
       | medium state complexity they're usually enough
       | 
       | For big stuff, especially deeply nested trees, MobX is still my
       | favorite. It has some quirks but the core premise is such a
       | simple and ergonomic mental model to work with, even for very
       | complex state with intermediate derivations
        
         | manx wrote:
         | What are the quirks?
        
           | brundolf wrote:
           | 1. It's an add-on, so eg. you have to manually wrap each
           | React component in an observer(), it doesn't really interact
           | with hooks (triggering or responding to updates), etc
           | 
           | 2. It has some minor gotchas around object cloning, proxies,
           | memory usage, and stuff like eg. certain functions have to be
           | pure
           | 
           | But in practice these aren't big barriers; once you get used
           | to them they fade into the background. And I've made stuff
           | with MobX that I'm not sure I could have built with any other
           | state management system. It's also one of the best-performing
           | ways to write React apps because it can be absolutely
           | surgical about only re-rendering exactly the things that need
           | to update, even moreso than the official state management
           | system
        
       ___________________________________________________________________
       (page generated 2022-12-25 23:02 UTC)