[HN Gopher] The new wave of React state management
___________________________________________________________________
The new wave of React state management
Author : remrem
Score : 170 points
Date : 2022-07-02 14:31 UTC (8 hours ago)
(HTM) web link (frontendmastery.com)
(TXT) w3m dump (frontendmastery.com)
| m_ke wrote:
| Mobx solved all of the state problems properly a long time ago.
| jetako wrote:
| Shoutout to MobX-state-tree
| speedgoose wrote:
| It is a lot slower though, I had to migrate from it to normal
| mobx to come back to descent performance when having a few
| thousand objects.
| tomduncalf wrote:
| Seconded, I looked at using MST a few years ago for a React
| Native app with frequent (30hz maybe) state updates and the
| CPU hit compared to plain MobX was too much
| phaedryx wrote:
| That's actually what converted me to Vue. I did all of the
| Redux stuff, but then found Mobx and enjoyed that so much more.
| A friend of my told me "if you like React + Mobx you'd probably
| like Vue" (I think he was quoting from the Vue website). He was
| right.
| pweissbrod wrote:
| Agreed! I'm surprised at the comprehensive work going into
| researching the history of state management in this article
| while completely missing MobX.
|
| What problem does MobX not already solve?
| Chris_Newton wrote:
| _What problem does MobX not already solve?_
|
| I'd say the two biggest hazards with the reactive/declarative
| style are cyclic dependencies in the data model and
| remembering history.
|
| Tools like MobX let you write quite elegant code in the right
| circumstances but they are less helpful if, for example, you
| have a complicated set of constraints and the effects of
| changing one value in your state can propagate in different
| directions depending on what first changed to start the
| cascade.
|
| This style also tends to emphasise observing the current
| state of the system, so if you need a history as well (for
| undo, syncing with other user actions via a server, etc.)
| then you probably have to write a whole extra layer on top,
| which is more work with this kind of architecture than for
| example if you are using a persistent data structure and
| reducer-style updates (as popularised by Redux within the
| React ecosystem).
| tomduncalf wrote:
| This is a really great explanation - I love MobX in many
| ways but the "observing the current state of the system"
| definitely has its downsides, which you've expressed very
| clearly!
| jitl wrote:
| All cited frameworks solve the problems. Article is more of a
| survey. It's a pity to miss Mobx while discussing
| proxy/mutation API in Valtio.
| tommoor wrote:
| came here to say the same thing.
| kabes wrote:
| Mobx has made me finally appreciate frontend programming again.
| It's like people want to deal with the insanity that is redux
| only because it's a more pure functional style which react
| seems to promote.
| Rapzid wrote:
| Something I like to point out to teams when it's the case,
| and it's often the case, is "When is the last time anyone on
| the team has used time travel debugging? Never?".
| acemarke wrote:
| Depends on what you mean here specifically :)
|
| I'll agree that the Redux DevTools "skip action" and "jump
| back to action" features are not all that commonly used in
| practice. I _maintain_ Redux, and I don't even use them
| that often.
|
| On the other hand, the ability to see a written list of all
| dispatched action type names is valuable by itself. So is
| the ability to click one of the listed actions and see the
| action contents, state diff, and final state. _That_ is
| very powerful.
|
| Beyond that... I now work at a company called Replay (
| https://replay.io ), and we're building a true "time
| traveling debugger" for JS. Our app is meant to help
| simplify debugging scenarios by making it easy to record,
| reproduce and investigate your code.
|
| The basic idea of Replay: Use our special browser to make a
| recording of your app, load the recording in our debugger,
| and you can pause at any point in the recording. In fact,
| you can add print statements to any line of code, and it
| will show you what it would have printed every time that
| line of code ran!
|
| From there, you can jump to any of those print statement
| hits, and do typical step debugging and inspection of
| variables. So, it's the best of both worlds - you can use
| print statements and step debugging, together, at any point
| in time in the recording.
|
| Additionally, because Replay records the browser's OS
| calls, it captures _everything_ that happens in the page.
| That means you can debug _any_ website or JS app, no matter
| what framework it uses - React, Vue, Angular, Svelte,
| jQuery, or vanilla JS.
|
| I actually recently implemented a POC version of support
| for the Redux DevTools in our Replay debugging app, so that
| if you do record a Redux app (or Jotai, or Zustand, or
| NgRx), you can use that same Redux DevTools UI to see the
| action history.
|
| So, yes, time travel debugging _is_ an amazingly powerful
| concept. It's just ironic that that particular aspect of
| Redux didn't end up getting used that much... but the Redux
| DevTools themselves are still valuable, and Replay is
| actually a far superior "time travel debugger" overall.
| Rapzid wrote:
| Time travel debugging is fantastic and it's a shame
| Chakra was shelved and we have no great OSS alternatives
| in the works at the VM level.
|
| What I meant though, was that people get hung up on the
| some ideal of how Redux is and will work for them while
| the reality is often quite different.
| DonHopkins wrote:
| >For example with local UI state, prop drilling both data and
| methods to update that data often becomes a probably relatively
| quickly as things grow.
|
| Can anyone parse that sentence please? Was this article written
| by GPT-3?
| andrewljohnson wrote:
| probably->problem is a typo, and prop drilling is lingo for
| digging down a large chain of components I think.
| rpeden wrote:
| Prop drilling in this context is just passing both state and
| update function(s) for that state into a component via its
| props.
| hellohowareu wrote:
| arcturus17 wrote:
| > never heard of tools
|
| These libs are at 4.7k, 8.9k and 17.1k stars on GitHub...
|
| > discuss the deep inner workings of things
|
| The article is a few thousand words and there are a few
| interesting reflections...
|
| > of things that already exist
|
| The point of the article is to actually talk about "new wave
| stuff"...
|
| You are arguably incorrect on many fronts, but more
| importantly, did you have to spend this many words being an
| utter dick to the author?
| nwh5jg56df wrote:
| Just what the world needed
| [deleted]
| shroompasta wrote:
| Zustand is a lot more popular than the comments or the article
| implies. I see it quite heavily used amongst Netflix engineers.
|
| That being said, prop drilling was made more of an issue than it
| really is, especially considering the boilerplate needed for
| state management libraries like Redux.
|
| But if there does need to be a global store, I usually reach for
| zustand as the API is probably the easiest out of the ones
| mentioned.
| UmbertoNoEco wrote:
| Or you just manage state in the server. With
| https://inertiajs.com/ you can even afford to not to declare an
| API and still manage the state back there.
| ramesh31 wrote:
| >Or you just manage state in the server. With
| https://inertiajs.com/ you can even afford to not to declare an
| API and still manage the state back there.
|
| Then we can party like it's 1999!
| UmbertoNoEco wrote:
| As God has always intended
| ramesh31 wrote:
| I'm just tired of the redundant reinvention of new "terms" for
| literally everything in JS. I don't want to know what an "atom"
| or a "proxy" or a "thunk" is. These are meaningless abstractions
| that simplify down to a store and a callback. Stop inventing
| terms to make yourself feel smart.
| acemarke wrote:
| FWIW, the term "thunk" is a long-standing CS term that long
| predates Redux [0] [1] [2].
|
| In fact, my first job back in 2008 involved a C++-based
| emulator/VM framework, and the devs used "thunk" to refer to
| jumping from the original program binary out to
| altered/replacement code written as C++ to add additional
| behavior or replace functionality.
|
| "Proxy" is also a long-standing term as well that describes
| wrapping or replacing functionality of a system, which is why
| it's used for HTTP servers and why it got used for a new JS
| capability in the ES2015 language spec.
|
| [0] https://en.wikipedia.org/wiki/Thunk
|
| [1] https://stackoverflow.com/questions/2641489/what-is-a-thunk
|
| [2]
| https://devblogs.microsoft.com/oldnewthing/20081020-00/?p=20...
| mechanicum wrote:
| And "atom" comes from Clojure's atomically updatable state.
| [0] [1]
|
| [0] https://clojure.org/reference/atoms
|
| [1] https://news.ycombinator.com/item?id=23183385
| petilon wrote:
| The "state management problem" appears to be an invention of
| React. This didn't use to be a problem with MVC. The state lives
| on the server. When state changes it should be persisted on the
| server immediately (in case the user unexpectedly closes the
| browser). On the client all you need is a cache.
|
| With MVC, each page is more or less independent. Each page gets
| the data it needs from the server (through a client-side cache),
| then updates the server when something changes. No "state
| management problem". In contrast, ReactRouter sees the entire
| application as one humungous component. Therein lies the problem.
| bcherny wrote:
| Your causation is reversed.
|
| People demanded more interactive web apps, which led to more
| stateful UI, which led to React.
|
| In the case of Facebook, the motivating app was Ads Manager --
| an enormous, highly interactive single page app for
| advertisers. You couldn't build something like it with HTML +
| server endpoints; in the pre-web days, apps with this kind of
| complexity would be desktop apps.
|
| Google Docs, Google Sheets, Maps, Spotify -- these all have a
| huge amount of client-side state. You can't represent that
| state on the server without making the UI unusably slow. The
| need to build these kinds of apps in a portable way led to
| complex state, which React tried to address (so did Angular,
| Ember, Backbone, etc.).
| petilon wrote:
| > _You can't represent that state on the server without
| making the UI unusably slow._
|
| And that's why you use a client-side cache.
| xeromal wrote:
| And once that cache is sufficiently complex, it's just a
| state store like redux.
| petilon wrote:
| Cache stays simple even for large applications. It never
| gets "sufficiently complex".
| xeromal wrote:
| Theoretically, but not practically.
| ekidd wrote:
| As the joke goes, there are two hard problems in
| software:
|
| 1. Naming things.
|
| 2. Cache invalidation.
|
| 3. Off-by-one errors.
|
| Caches are tricky beasts. First, you need to update them
| when the server-side state changes (for example, two
| people editing a single Google doc). Second, writing
| state changes to the server and waiting for confirmation
| is too slow for many kinds of interactions. In these
| cases, it's typical to optimistically write local changes
| to a local store, and then try to sync those changes with
| server asynchronously. But if synchronization fails, then
| the client needs to report that.
|
| And finally, there's the problem of partially loaded
| state, where the rest is loaded asynchronously on demand.
| That _should_ be simple, but without some kind of
| framework, it also tends to have lots of subtle state-
| machine and null-reference bugs.
|
| So, no, cache does not always stay simple in large
| applications. (Unless the app is read only, and you're OK
| showing stale data.)
| petilon wrote:
| If you are building Google doc editor by all means,
| design a complex state management system, it is worth it.
| But then don't bring that complexity into typical
| business applications.
| kaoD wrote:
| And that's why you need state management. Cache is state.
| pweissbrod wrote:
| I used to think the same thing until I considered that single
| page app development is really just a reinvention of thick
| clients.
|
| When you look at an SPA as a thick client state management is a
| natural thing as it was in Java swing and WPF and Windows forms
| and other stacks beyond my knowledge
| jitl wrote:
| I came to understand MVC (model-view-controller) from writing
| Objective-C desktop software (https://developer.apple.com/libra
| ry/archive/documentation/Ge...).
|
| The "M" in that MVC is "Model", which is the same idea as
| "state management". It's an object that stores state and
| notifies listeners when it changes. You can think of these
| libraries as ways to implement the "Model" concern in the
| application.
|
| But from your use of MVC, I think you are referring to server-
| side MVC, where the "V" is a rendered HTML template? I'm not
| sure how to square the desktop software version of MVC with
| your assertion that state should only exist on the server.
|
| My Cocoa desktop apps ran fine 10 years ago without a server.
| The React application I work on today has many bits of local
| state it needs to track like "what is selected?", "how wide is
| the sidebar?", and "should this menu be open?". I don't think
| the server should be involved in such matters.
| petilon wrote:
| I am talking about client-side MVC. Models should be POJO
| [1], no library needed.
|
| [1] https://en.wikipedia.org/wiki/Plain_old_Java_object
| s-lambert wrote:
| React wasn't the first complex frontend framework, arguably
| people were having these state management problems ever since
| people started doing more stuff like jQuery UI. It's not tied
| to SPAs either, you can have state management problems for a
| single URL as long as it has any form of state change (like
| opening a modal).
| wilde wrote:
| This is true until your customers complain that your UI is
| super slow. You realize they're trying to use your app from a
| cell phone with poor service. So you have the genius idea to
| add optimistic updates in JS. Now you have all the problems
| from the article since you need to update all the components
| everywhere on screen that share state.
| pcthrowaway wrote:
| > Now you have all the problems from the article since you
| need to update all the components everywhere on screen that
| share state.
|
| If anyone can field a question about react-query here, this
| seems like one of the exact problems I thought it solved when
| I started using it.
|
| I _do_ enjoy using it, but requesting the same data with the
| same key+queryFn from multiple, unrelated components still
| generates regular requests at the configured interval (even
| if I 'd want/expect those components to share the response
| and only make that request at whatever rate satisfies the
| shortest configured interval)
|
| Am I missing something in my configuration here?
| frosted-flakes wrote:
| React-Query is very aggressive about refreshing the cache
| by default, including whenever the browser receives focus,
| on a set schedule, and automatically retrying failed
| queries multiple times, these can all be disabled. If any
| queries use the same key they _should_ share data, but I
| haven 't experimented with it enough to learn all its
| intricacies.
| petilon wrote:
| All you need is a client-side cache.
| wilde wrote:
| How do changes to that cache get displayed? Your cache
| emits events that each UI element has to listen to?
| Congrats you're using redux!
|
| (It would perhaps be more accurate to say that React folks
| had to reinvent these patterns, but the problems were
| definitely present in the postback era)
| petilon wrote:
| > _Your cache emits events that each UI element has to
| listen to?_
|
| It doesn't. How often do you have the same information
| redundantly displayed in multiple places, on the same
| screen?
| ativzzz wrote:
| It's not even necessarily the same information, but small
| pieces of one bigger piece that need to be updated once
| some of the other smaller pieces change
| wilde wrote:
| Yeah this. The classic is unread state in a mail app.
| Unread state is usually displayed both as bold state per
| message in a message list, and as a count in the folder
| list. These need to stay in sync as the user reads mail
| (and sometimes marks read state explicitly). Two views of
| the same underlying state.
| petilon wrote:
| Sure, you can come up with an example where some
| synchronization is needed, but how often do you have this
| requirement? In most apps it is rare, which means that it
| can be solved by using a couple of extra lines of code to
| update the screen, as opposed to adopting a complex state
| management system with events firing and so on. Simple
| solutions for simple problems.
| lhnz wrote:
| That is exactly what the React state management solutions
| all are...
| monkaiju wrote:
| Really surprised there was no mention on MobX. I've used int for
| lots of projects and loved it.
| glenjamin wrote:
| I find it very disappointing that this article does not attempt
| to draw a distinction between state management for complex local
| states (imagine an image editor), or state management for
| fetching and updating data via APIs
|
| I think the shape of solution needed for these two problems are
| quite different.
| lloydatkinson wrote:
| Same here. Local state and server state are not always the
| same. I see a lot of people saying how replacing redux with
| react query worked well and that's great but there's definitely
| times when you have a lot of state in a client side heavy SPA.
| The distinction should really be highlighted more.
| gloryjulio wrote:
| Exactly. I think people who complains about complexity of some
| of the tools, just have not worked on the complex webapp(not
| the webpage) before. Unfortunately these 2 always get
| conflated.
| ashishb wrote:
| Afaik, Vue ships with batteries included.
| fabian2k wrote:
| For me the issue of state management mostly went away after
| starting to use React Query. It turned out that the most
| problematic state was server-side state for me, which is handled
| very well by libraries built for that purpose.
|
| The state that remains is often simple enough that plain old
| React state management with useState/useReducer is sufficient. A
| lot of state can be local, and local state is easy to handle with
| the built-in tools of React. And global state is only really an
| issue if it changes often. For mostly static state like
| information about the current user, theme or UI settings and
| similar kinds of state using React Context works perfectly fine.
|
| Of course this depends heavily on the kind of web application you
| write, if your application is closer to Photoshop in the browser
| than a simple CRUD app you probably can make good use of more
| complex state management libraries.
| bernawil wrote:
| The state that remains is often simple enough that plain old
| React state management with useState/useReducer is sufficient
|
| hah this is an understatement. For hooks, the React runtime
| already does a ton of non-standard-js things under the hood.
| useState gives a method to update and "subscribes" a component
| to updates on the hook's value. Put that code in a custom hook,
| export it and you re-invented Redux. In fact, exporting a
| single big useReducer for all your state gives you something
| almost identical to old style Redux.
| acemarke wrote:
| FWIW, there _are_ a number of technical and conceptual
| differences between Context+`useReducer` and Redux. I wrote
| an extensive post describing those differences and potential
| use cases for each:
|
| https://blog.isquaredsoftware.com/2021/01/context-redux-
| diff...
| ggregoire wrote:
| Exact same experience here. We were using Redux to manage
| server-side data and switching to React Query massively
| simplified everything. It appears that managing server-side
| data in an efficient way is an insanely complicated topic and
| React Query just solved everything about it that I can think
| of.
| acemarke wrote:
| Yeah, both the React Query and Redux maintainers agree that
| you shouldn't be writing data fetching and caching logic
| yourself. That's why we recently added a new "RTK Query" data
| fetching and caching API to Redux Toolkit, so that if you're
| using Redux it handles that work for you:
|
| - https://redux.js.org/tutorials/essentials/part-7-rtk-
| query-b...
|
| - https://redux-toolkit.js.org/rtk-query/overview
|
| and if you're just using React, definitely look at React
| Query.
| ggregoire wrote:
| Yes we chose Redux 6 years ago for data fetching and
| caching when there wasn't as many alternatives as today!
| acemarke wrote:
| Hah, yeah, the ecosystem landscape has definitely changed
| over the last few years :)
| likortera wrote:
| I've only used SWR. How does it compare? I
| krall12 wrote:
| SWR does basically the same core thing (query, cache and
| mutation help) with less features.
| cercatrova wrote:
| Redux now has its own query solution as well, it's pretty
| useful [0].
|
| [0] https://redux-toolkit.js.org/rtk-query/overview
| kasane wrote:
| This matches my experience as well. Additionally, React Query
| has support for features like retries and caching.
| cehrlich wrote:
| Agree completely, React Query has made it so much easier to
| build any kind of app that deals with server state, stuff that
| would have been extremely challenging to write in the past is
| now just a couple of lines and works better than before.
|
| I personally like using Jotai (if I just want a better version
| of React Context) or Zustand (if I need a bit more than that)
| for "client state" alongside React Query, but I've also built
| projects where I didn't need a client state management solution
| at all.
| celim307 wrote:
| React query is one of the highest quality react libraries I've
| ever used
| weeksie wrote:
| The problem with redux is that it's a simple, extremely powerful
| tool for creating a CQRS architecture on the front end but very
| few people treat it that way. Instead they bolt on things like
| rtk and add yet another layer of abstraction over their project.
| In those cases it's almost always better to just use something
| small and simple like Zustand, which the article called out.
|
| For bigger projects, custom middleware is where the magic is. If
| you don't understand redux well enough to write your own
| middleware (it's not very complex, it's just under documented for
| some reason) then it's better to use one of the other, simpler
| abstractions instead of adding one abstraction (redux) then
| piling on more abstractions to make it usable.
| acemarke wrote:
| Pretty sure you and I debated "vanilla Redux" vs RTK in a
| thread a couple years ago, but I'll link my most recent
| explanations of why RTK is the right way to use Redux today:
|
| - https://redux.js.org/introduction/why-rtk-is-redux-today
|
| - https://blog.isquaredsoftware.com/2022/06/presentations-
| mode...
|
| Also, note that RTK has a new "listener" middleware that
| simplifies the process of "run this code when some action is
| dispatched". You can certainly still write a completely custom
| middleware if you _want_ to, but the listener middleware
| handles that work for you.
| weeksie wrote:
| I get it, you're _really_ invested in RTK but man, I just
| find it to be the right answer to the wrong question.
|
| Since we last talked I have worked on projects where rtk was
| used because the devs didn't really grok redux and so far
| that's the best use case I've run across. That said, now when
| I run across situations like that I tend to guide clients to
| simpler state management solutions instead of piling on
| another layer of abstraction.
| civilized wrote:
| Curious layman here (no web dev experience). I thought the main
| selling point of reactive programming was that it abstracted away
| the need to manage state. What problems, then, does a state
| management library solve in a reactive framework?
| chrisco255 wrote:
| As we know from computer science, there are two difficult
| problems: naming things and cache invalidation. State
| management is inherently difficult in web apps (I think it's
| inherently difficult for any complex application). They are
| effectively distributed systems with local caches and remote
| server data that need to be synced correctly in order to manage
| a user application at scale. That all has to align with how the
| presentation logic is built. It has to deal with the
| constraints of the web platform, etc.
| tadfisher wrote:
| Reactive programming provides the capability to _react_ to
| changes in state. You still need to hold that state somewhere,
| mutate the state from your reactive code, and control the
| lifetime /scope of that state. Managing state becomes _more_ of
| a concern with reactive programming, but it also becomes very
| explicit; this is something that traditional MVC approaches try
| to hide, to the detriment of anyone trying to understand the
| data path of your application.
| ksbrooksjr wrote:
| Most state management libraries help you deal with the problem
| of sharing state between multiple components. In modern React,
| most components are just functions, so this boils down to
| passing state through deep call stacks.
|
| If you have a component A, which renders component B, which in
| turn renders component C, without a state management library
| you'd have to pass state from A to B to C (this is often called
| prop drilling). The longer the call stack, the more irritating
| this becomes.
|
| State management libraries allow component C and component A to
| modify, and subscribe to a shared state store. Redux et al. are
| effectively the reactive version of global variables.
| bayesian_horse wrote:
| I didn't get the memo apparently. I still think
| Redux+Thunks+Selectors+Sagas is great and that combination solves
| all my problems. Boilerplate isn't negligible but relatively
| tame. There's a straightforward way how to model state, and I
| don't have to put too much logic (especially async) into
| components.
|
| But that's just me...
| chrisco255 wrote:
| Yeah I've always thought the complaints about boilerplate were
| misguided. Whatever the cost in boilerplate implementation was
| more than made up for by having predictable, deterministic UI
| output. That being said, I think hooks did open up the state
| management design space quite a bit and classic redux style
| state management doesn't quite line up with it. Still totally
| valid as an architecture, though, in my opinion.
| ezekiel11 wrote:
| I ditched React/Redux for Vue 3 & Pinia and my god, what a world
| of a difference. Everything is intuitive and I am not googling
| days to fix tooling issues, or having to do it the React/Redux
| way which was honestly overly engineered and non-productive.
|
| Frontend shouldn't be complicated and we've been lied to, you are
| not Facebook, you don't have billions to throw at engineering,
| you must pick the path of list resistance
| MentallyRetired wrote:
| Bingo. React is great for insane amounts of fine grained
| control.
|
| But I don't want that. I want to build interfaces and not
| "manually shift" my local state management.
| 42e6e8c8-f7b8-4 wrote:
| I believe the worst part is redux. React is mostly reasonable.
| Redux is massive boilerplate.
| kizer wrote:
| "Prop drilling". So many buzzwords. SSR, Hydration, Tree shaking,
| Hot module reload.
|
| How has web development gotten here? It just seems to have
| evolved so much needless complexity to me.
|
| Don't forget about web components! Integrated into the platform.
| cercatrova wrote:
| I've often found those that complain about these buzzwords are
| the people who do not actually do any frontend engineering.
| There are buzzwords in every language and every library. It's
| not an indictment of complexity (which exists outside of any
| one language or library), it is simply the terms of the trade
| of that particular technology.
| kizer wrote:
| I don't know why but front-end terminology always makes me
| cringe. I know it's useful jargon. I don't know why I have a
| visceral distaste for them. Maybe because it feels like
| taking a small, simple thing and making it seem like it's
| something more.
|
| But you're right. I haven't done much front-end at large
| scales. Only at one employer for a short while.
| cercatrova wrote:
| > _Maybe because it feels like taking a small, simple thing
| and making it seem like it 's something more._
|
| Perhaps it makes more sense to treat frontend engineering
| as thick client desktop development of yore. Websites are
| no longer small, simple things, they are now the primary
| apps that many people use (through the broswer and
| especially through Electron), so there needs to be
| sufficient tooling around managing that complexity.
| kizer wrote:
| You're right. That makes sense. I've been out of web dev
| for about 4 years so I'm just reactionary now I guess.
| dboreham wrote:
| You're experiencing the cognitive dissonance from trying to
| understand unnecessary complexity.
| nikodunk wrote:
| For anyone struggling with the complexity and boilerplate of
| Redux, at my day job we added Redux Toolkit (the newly
| recommended add-on by the Redux project itself!) and it solves
| most of the verbosity issues! We use it to share all our state
| logic over mobile and web and it works excellently now. I'd
| actually recommend Redux w/ Redux-Toolkit, for the first time
| ever.
| phreack wrote:
| There's a library called rematch that's been implementing most
| of these ideas for a long time, but sadly it didn't get popular
| enough and it seems to be somewhat lacking maintenance. It was
| such a pleasure to use (in comparison) that I just can't
| believe how people ever work with those massive switch
| statements.
| acemarke wrote:
| One of the reasons we created Redux Toolkit was to eliminate
| the need to write those switch statements :) (also action
| type strings, action creators, object spreads, having to
| split logic for one feature across multiple files, and all
| the other "boilerplate" concerns that users rightfully
| complained about over the years.)
|
| - https://redux.js.org/tutorials/fundamentals/part-8-modern-
| re...
|
| - https://redux.js.org/tutorials/essentials/part-2-app-
| structu...
|
| - https://blog.isquaredsoftware.com/2022/06/presentations-
| mode...
| sebmellen wrote:
| For anyone who has not had the pleasure of working with these
| simpler "atom-based" state management libraries, I would implore
| you to try Jotai (https://jotai.org/), which is mentioned in the
| article.
|
| Jotai's atomic model and ease of use has made writing complex
| React applications far more joyful for me.
| LAC-Tech wrote:
| I think the obsession the react space has with "state management"
| is a by-product of how incredibly convoluted reacts rendering is.
|
| The other reason is a lack of exposure to how other technologies
| for GUIs have handled state for decades.
|
| Maybe look outside the react bubble and see how many of these
| "issues" just disappear when you stop acting like react is some
| fundamental particle of the web.
| wereHamster wrote:
| Weird that XState was not mentioned.
| aarpmcgee wrote:
| Agree. I am working on a side-project and using XState for
| local state management, and Jotai (with Immer) to send that
| state to various components in my app. It is working really
| well and mitigating unnecessary rerenders.
|
| More moving parts than I might like, but they play together
| nicely and I haven't hit a single wall yet.
| johtso wrote:
| For me using xstate was a game changer. Pulling logic out into a
| state machine gives you so much clarity over your application
| logic. Also nice to have your business logic defined with
| something that is framework agnostic.
| ramesh31 wrote:
| Once you see the light of state machine based UI's, it's
| immediately obvious and you never want to go back. The problem
| comes in convincing others to deal with the boilerplate. It's
| worth it, but it never really sinks in until you use it.
| CitizenKane wrote:
| I've had this same experience as well! Wrapping your head
| around the concepts at first can be a little tedious but it
| makes application logic and behavior far more predictable. The
| ability to visualize them is the icing on the cake as well and
| is a nice extra tool that eliminates the need for arrows and
| boxes in a sketchbook or a Google Drawing.
| nine_k wrote:
| Yes! An explicit state machine is my desire for the UI
| development since the Delphi days of 1990s. It makes things so
| much more observable and sane.
|
| Redux nudges you to build that state machine by hand, in the
| form of the reducers folder, around the centralized state.
| While elucidating, it's still a lot of boilerplate (which you
| can sort of factor out), and it's still not one clearly laid
| out entity.
| acemarke wrote:
| 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.
| aarpmcgee wrote:
| This looks excellent. I see a lot of potential in the idea
| of combining the strengths of RTK(+Query) and XState. Thank
| you for sharing!
| acemarke wrote:
| Yeah, if you've got any particular use cases or ideas for
| how you'd like to use them, please put up a discussion
| thread in the RTK repo and let's talk!
| todd3834 wrote:
| I've been using redux ever since it came out and a home rolled
| flux architecture before that. I gotta say I've been using
| zustand lately and it feels so effortless compared to other
| solutions. I couldn't imagine going back to redux. Although redux
| slices feel a little bit closer.
| Waterluvian wrote:
| I used Redux and loved it until I moved to typescript. Then there
| was a terrible amount of boilerplate and magic. So I wrote my own
| 75 line alternative that does a bare minimum. It's basically just
| a useContext wrapper. And I haven't looked back since.
|
| This is for pure client side stuff, of course.
| acemarke wrote:
| Hi, I'm a Redux maintainer. FWIW, we specifically designed our
| official Redux Toolkit package to not only eliminate the
| general concerns about Redux "boilerplate" [0] [1], but also
| work great with TS. With our recommended RTK+TS usage patterns,
| a typical "slice reducer" file only needs to define a type for
| the reducer's state, and then define a case reducer as `(state,
| action: PayloadAction<MyData>`) [2], and that's it.
|
| We've put a _lot_ of work into making sure that our library TS
| types minimize the amount of types that you have to write in
| your own app code.
|
| Also, one of the reasons we now teach the React-Redux hooks API
| as default is that it's drastically easier to use the hooks
| with TS than the legacy `connect` API.
|
| If you haven't had a chance to see what "modern Redux" looks
| like, I'd suggest going through our docs tutorials to see how
| we want people to learn and use Redux today [3]
|
| [0] https://redux.js.org/introduction/why-rtk-is-redux-today
|
| [1] https://blog.isquaredsoftware.com/2022/06/presentations-
| mode...
|
| [2] https://redux.js.org/tutorials/typescript-quick-start
|
| [3] https://redux.js.org/tutorials/index
| monroewalker wrote:
| RTK is what made redux usable for me. I can't imagine using
| redux without it. ^ Mark is also very active and responsive
| in the Reactiflux discord and has directly helped me and
| countless others clear any hurdles with its use
| Waterluvian wrote:
| Hooks made react and redux far less ridiculous. Class based
| react and redux wss maddening.
|
| I'll poke again but last time I tried I couldn't avoid
| Typesafe Actions library.
| acemarke wrote:
| Yeah, _please_ don't use `typesafe-actions` :)
|
| It may have had some value before RTK came out, but a lot
| of the opinions and approaches shown in its docs lead you
| to write _wayyyy_ too much code. For example, we
| specifically recommend _against_ writing TS unions for
| action object types [0].
|
| RTK completely obsoletes `typesafe-actions`, and the TS
| usage patterns that we teach today should result in a
| pretty minimal set of types that you need to write in your
| own code.
|
| For a small example see the RTK+TS template for Create-
| React-App [1]. If you want to see what a real app codebase
| can look like, the client app for my day job at Replay.io
| is OSS [2]. It's admittedly a somewhat messy codebase due
| to its long evolution and legacy (started as the FF
| DevTools codebase, copy-pasted, and we've been slowly
| migrating to RTK+TS and modernizing it), but files like [3]
| show how I would write a real slice reducer with RTK+TS.
|
| [0] https://redux.js.org/usage/usage-with-typescript#avoid-
| actio...
|
| [1] https://github.com/reduxjs/cra-template-redux-
| typescript
|
| [2] https://github.com/replayio/devtools
|
| [3] https://github.com/replayio/devtools/blob/454804188d339
| 00a26...
| cercatrova wrote:
| Context and Redux are somewhat different tools and context
| doesn't necessarily solve the same problems as Redux. This
| article by the maintainer of Redux (acemarke) goes over why
| (looks like he replied to you as well) [0]. Have you tried
| Redux Toolkit as well? It cleans up a lot of the complexity of
| Redux and works well with TypeScript [1].
|
| [0] https://blog.isquaredsoftware.com/2021/01/context-redux-
| diff...
|
| [1] https://redux-toolkit.js.org/
| Waterluvian wrote:
| Basically I'm not saying redux is bad. Just that after years
| of using it for production software I concluded it's still
| overkill for my needs.
|
| IIRC Redux is also just an abstraction on top of Context.
| Fundamentally it gives you pseudo-global access to
| application state by being able to interact with it anywhere
| in the component tree below the context manager.
| acemarke wrote:
| > Redux is also just an abstraction on top of Context
|
| No, this is a very common but incorrect misunderstanding of
| how Redux works.
|
| It's true that React-Redux does use context internally...
| but only to pass down the Redux store instance, _not_ the
| current state value.
|
| Also, because Redux itself is separate from React, there's
| a lot of things you can do with it that are completely
| different than what Context does. _One_ bit of overlap is
| that both can be used to access state across the component
| tree, but Redux does much more than that.
|
| See my post here for more details:
|
| https://blog.isquaredsoftware.com/2021/01/context-redux-
| diff...
| aerovistae wrote:
| I'd like to share my approach to React state management, because
| after a decent amount of industry experience I've stumbled onto a
| solution I find to be very excellent.
|
| Firstly, I use the open source library Pullstate[1], which I find
| to be as effective as any alternative but _far, far_ simpler to
| understand and use.
|
| All my components are functional components. For any state that
| _only_ that component needs, of course I simply use the useState
| hook.
|
| When things need to be shared among multiple components, I create
| a Pullstate store - for instance, for an app I'm working on now I
| have a UiStateStore like so: type UiStateStore
| = { isSidebarOpen: boolean; // etc };
| export const uiStateStore = new Store<UiStateStore>({
| isSidebarOpen: false, });
|
| Then, in the components that need to know if the sidebar is open,
| I import this store and use its state hook _the exact same as the
| normal useState hook_, like so: const
| isSidebarOpen = uiStateStore.useState(s => s.isSidebarOpen);
|
| You simply pick which properties you need off the state object
| ("s"). When you open the sidebar, you simply update the store
| like so: onClick={() => { uiStateStore.update(s
| => { s.isSidebarOpen = true; }) }}
|
| And automatically, any components using uiStateStore.useState and
| watching the isSidebarOpen property will get updated, exactly the
| same as the normal useState hook - just shared.
|
| It's so dead simple and has made complex app-building so much
| easier for me.
|
| By comparison, Redux in my experience has a harder learning curve
| with a lot of unnecessary pieces and boilerplate - it seems crazy
| to me that people think it's a great solution and it feels like
| people have convinced themselves all those pieces are
| "necessary", where in my experience they are anything but.
|
| The one caveat is that if I have a component with many handlers,
| e.g. onClick, onMouseMove, onContextMenu, onMouseLeave, etc (and
| in some cases I do), components can get bloated. I haven't found
| a fix to that yet. But that's more an inherent issue with react
| than anything to do with state management.
|
| [1] https://github.com/lostpebble/pullstate
| have_faith wrote:
| You might like the atomic state management libraries mentioned
| in the article, they simplify things to another level because
| they sort of remove the concept of a store entirely. For
| example in Recoil I would do this: export
| const isSidebarOpenAtom = atom({key: 'isSidebarOpen', default:
| false});
|
| And in the component: (it mimics useState)
| const [isSidebarOpen, setIsSidebarOpen] =
| useRecoilState(isSidebarOpenAtom);
|
| and later... setIsSidebarOpen(true)
|
| Recoil will then re-render any component that relies on
| isSidebarOpen.
|
| The only real boilerplate is having to specify keys for each
| atom, which I find a small price to pay for such simple global
| state.
| etimberg wrote:
| In some ways this feels a lot like http://alt.js.org/
| doodlesdev wrote:
| I'm pretty sad this is the point we are at with React frontend
| development, the library is becoming much larger than it's
| original scope and it's getting bloated while not solving the
| essential problems that happen. In my opinion the best solution
| we have right now for frontend JS development is to not use JS or
| JSX at all and instead use a DSL such as Svelte, this way the
| compiler abstracts all complication and there is no application
| bundle size bloat. Obviously we have Preact (which solves react-
| dom bloat), MobX (which solves state management), etc. which are
| all great tools but the problem is that every tech stack is
| different and the more the core technology can do without getting
| more bloated the easier it is to introduce new developers to a
| codebase and keep up with changes.
| sachinraja wrote:
| How is React not solving essential problems? Suspense solves a
| pretty essential issue. Also Svelte can quickly increase in
| bundle size and if you have enough components, it can become
| bigger than the equivalent in other frameworks:
| https://github.com/yyx990803/vue-svelte-size-analysis.
| doodlesdev wrote:
| The first version of React was released on 2013, it took
| almost 10 years for Suspense to exist (we _just_ got it now
| with React 18), that's what I'm talking about. Even
| functional components and hooks took a lot of time from them
| get and implement the idea after they tried to use ES classes
| and made everything much harder to manage. Context also isn't
| perfect, I like it but the redraw performance is not amazing
| and doesn't scale at all to bigger applications.
|
| > https://github.com/yyx990803/vue-svelte-size-analysis
|
| This is an interesting comparison I haven't seen before, I
| wonder if it's true for a complete application using some lib
| for state management, routing, etc. and if this isn't just a
| kind of cherry picked example. Thanks for showing this
| though.
| nine_k wrote:
| Svelte does wonders to code size, indeed.
|
| But does it solve the problem of growing state which never gets
| GC'd when components which used to use it are gone? Does it
| solve the problem of only redrawing the required minimum
| (beside the normal VDOM approach)?
|
| I'm asking as someone not knowledgeable enough about Svelte.
| doodlesdev wrote:
| > Does it solve the problem of only redrawing the required
| minimum (beside the normal VDOM approach)?
|
| Yes, in fact I think it's actually pretty hard _not_ to
| redraw the bare minimum LOL. If you want to know more about
| Svelte (even if you're not looking to develop with it) I
| HIGHLY recommend listening to this presentation called
| "Rethinking reactivity" by Rich Harris (the creator)
| https://youtu.be/AdNJ3fydeao
|
| > But does it solve the problem of growing state which never
| gets GC'd when components which used to use it are gone?
|
| I think the answer to the question is yes. Although the
| problem I'm speaking mostly about state management is the
| source of truth problem. Svelte provides a global store to
| store data, and data stored on local components are just
| _variables_ (no useState or hooks or anything complicated)
| where the Svelte compiler handles everything.
|
| Something else I'm really eyeing right now is SolidJS which
| takes a very similar approach to Svelte (compiler instead of
| library) for frontend development but provides an API that's
| very familiar to React developers so there's not much of a
| learning curve (although Svelte has a very easy learning
| curve too).
| rglover wrote:
| This is why I'm building Joystick:
| https://github.com/cheatcode/joystick.
|
| It riffs on the old, simple APIs of React but uses pure HTML,
| CSS, and JavaScript w/o any trickery (I'm also hardcore about
| _not_ changing the component API so WYSIWYG).
|
| The bonus is that it's a part of a full-stack framework (the UI
| framework has a Node.js counterpart), so wiring up a full app
| is near-effortless.
| doodlesdev wrote:
| Looks pretty interesting, I'm always kind of bothered about
| the lack of (true) full-stack frameworks for the NodeJS
| ecosystem that handles accounts, database, frontend, API,
| etc. like we have for Python with Django or C# with .NET.
| rglover wrote:
| Thanks. Likewise, and that's the driving motivation here.
| jeroenhd wrote:
| I've used Redux but I've never heard of any of these
| alternatives. I have no doubt they're popular, but what is it
| about frontend that makes everyone reinvent the wheel every five
| years? Everything from the tooling to the tiny details somehow
| expires and gets recreated in a similar-but-not-similar-enough
| way that keeps the ecosystem in a constant state of flux.
|
| Is it the lack of platform API support? Is it the community
| trying to make everyone a library developer? What's wrong with
| frontend?
| rglover wrote:
| A few different problems...
|
| "Necessity is the mother of invention" comes to play here. The
| reality is that the community _hypes_ certain tools, but in
| practice, they tend to have gotchas buried far beyond the
| surface level demos and documentation. The problem with that is
| that you only figure that out after committing to those tools
| and using them. This leads to tool abandonment, or in some
| cases, developers taking a swing at their own version. What
| they come up with is more often than not a rehash of the old
| ideas but lacking any "why" or long-term vision.
|
| The other one is employability by obscurity. An old grifter
| trick is to make something far more complicated than it needs
| to be as a means to guarantee employment (both on the tool
| developer side _and_ the end-user side). For the tool
| developer, the more they can twist and turn their tool
| (introducing novelty and potentially confusion), the more
| sought-after their services will be. For the end-developer,
| they can hold a "monopoly on intelligence" and become
| difficult to replace in a company because they're the only one
| that understands that thing. Couple this with the conference
| talk circuit where you see the same people constantly pitching
| some new-fangled widget every year and you realize the goal
| isn't to solve the problem, it's to get paid to _look like_ you
| 're solving the problem.
|
| Another problem is inexperience. A developer might have just
| enough experience to feel confident at the code-level, but they
| lack the practical experience to let them know why a certain
| pattern is incorrect. Assuming that they never get that
| practical experience, they will continue to iterate the tool
| into an utter mess or deprecation.
| gernb wrote:
| I considered something like this last night as I stay up to 6am
| working on a new UI library. My conclusion was in part because
| it's easy. The goal is well defined. I got the first widget
| working thought I'd call it a day (a night) but then it was so
| much fun to just implement the next widget mostly because very
| little design iteration is needed. The problem being solved is
| well known so each thing to tick off my UI lib was only a few
| minutes. Next thing I know it's 6am.
|
| I think the same is true of 3D libraries. The real work of
| making an app that does 3D is not the 3D engine, it's
| everything else (UX or GameDev). The 3D part has well known
| goals and solutions so it feels like you're making a ton of
| progress, ie, it's fun to make. Much easier than deciding
| harder things like which features your app should have and how
| they should work.
| sandinmyjoints wrote:
| Great insight, this makes a lot of sense. And on top of this,
| it SEEMS impressive. You made a whole framework! Wow! Plus
| there's a chance of widespread adoption---so, well-defined
| goals, fun to work on, seems impressive, potentially very
| high payoff. No wonder there are so many.
| [deleted]
| ggregoire wrote:
| It's the case in the backend and devops world too. But like for
| Redux you probably chose some decent libraries and tools at the
| beginning and sticked to it. If you start looking around you
| will see there are alternatives to everything you use, and even
| maybe that most of the industry moved to those alternatives in
| the past 5 years.
|
| How many ways are there to build an API? In Python: Falcon,
| Flask, Django, FastAPI and so on. Just as many choices in Java,
| Go, Node, <insert your favorite language>.
| xeromal wrote:
| "What's wrong with frontend?"
|
| This is the age-old question. You're using Redux now, but I'm
| sure some JQuery/Angular/Knockout/etc dev said the same thing
| about what you're using back then.
|
| The front-end is crazy and I don't think there's an obvious
| answer of why it's such a developmental disaster. It's easy to
| say it's run by script kiddies or the barrier to entry is too
| easy, but there are a lot of smart devs working on the top
| libraries. The culture just ended up this way. Whatever is
| driving it probably will never stop though. Enjoy the ride. lol
| dwaltrip wrote:
| Frontend end is crazy because many UIs that do useful things
| are inherently quite complex. UIs, by definition, are how
| people interact with software to solve problems and
| accomplish goals. The problems we solve and the goals we
| achieve with software are continually evolving and expanding
| as more and more software is created.
|
| The people-software interfaces for many of the commonly used
| pieces of software will always be complex as we will always
| demand a lot of our software, up to the limit that can be
| provided by the available tools for building these apps. As
| our capabilities for building better software grow, so too
| will the demands of the users.
|
| If you aren't buying this argument, sit down and map out
| every single possible state and every possible event (user
| interactions, etc) of a moderately-sized app that you use
| regularly. Or even just one page of that app. There's a lot
| going on. It feels simpler than it is when we are using it
| because well-designed applications become invisible to the
| users, especially as we become familiar with them. They "just
| work".
|
| TL;DR Reality is messy and complicated. And so is the
| software we build as well.
| etimberg wrote:
| I think it's because redux is quite painful to use with very
| modern apps. Most of the time you need something like `redux-
| saga` or `redux-thunk` to deal with async side effects. I'm not
| sure which is the most popular today, but sagas are based on
| generators and trying to use those with typescript is very very
| painful and the underlying issue [1] is marked as a design
| limitation in TS itself.
|
| In addition, if you want to have your app load as smaller
| chunks rather than a single large bundle, you need to be
| careful to ensure that things work even all the backing
| reducers aren't yet loaded.
|
| 1. https://github.com/microsoft/TypeScript/issues/32523
| doodlesdev wrote:
| In my experience the experience with Redux Toolkit is
| awesome, it's essentially an opinionated way to use Redux for
| modern web applications and I believe they really hit the
| mark when it comes to reducing boilerplate and the need for
| extra deps. Although I'm still not a big fan and prefer to
| use built-in tools of React to manage state when possible
| (now that we have Context, Suspense, etc.)
| kitten_mittens_ wrote:
| arcanis has a PR to patch up the issue that's sat for a year
| plus now.
| https://github.com/microsoft/TypeScript/issues/43632
|
| > In addition, if you want to have your app load as smaller
| chunks rather than a single large bundle, you need to be
| careful to ensure that things work even all the backing
| reducers aren't yet loaded.
|
| In the decade old application we use redux saga in at work, a
| large portion of our 7MB minified/gzipped main chunk is redux
| handlers. It'd be nice if there was a relatively simple way
| to not synchronously load all the reducers up front.
| acemarke wrote:
| We have docs on code splitting reducers and other Redux
| logic here:
|
| - https://redux.js.org/usage/code-splitting
|
| There have been some different community packages for
| helping with that process, but some of them seem to have
| become outdated (only worked with React-Redux v5, etc). I
| did see a new one at https://github.com/fostyfost/redux-
| eggs that seemed like it had potential, but I haven't had a
| chance to try any of them myself.
|
| I also once saw someone play around with the idea of using
| React's still-not-technically-final Suspense support to
| help ensure that a lazy-loaded component that relies on a
| code-split reducer doesn't actually get rendered until that
| reducer's state is available. Don't have the link handy
| atm, but if someone wants it ping me and I can go figure
| out where that was described.
|
| Also, the new RTK "listener" middleware was specifically
| designed to replace almost all saga usages, and you can
| dynamically add more listeners at runtime via dispatch an
| `addListener()` action:
|
| - https://redux-toolkit.js.org/api/createListenerMiddleware
|
| - https://blog.isquaredsoftware.com/2022/05/presentations-
| evol...
| weeksie wrote:
| You don't need _any_ of that. You can use vanilla redux and
| put your asynchronous code in middleware.
| Rumudiez wrote:
| More of this. Middleware is simpler to grok than reducers
| and provides a clean, universal solution to async. You
| don't need sagas, just dispatch events at meaningful points
| in time, like when a request is initiated and then another
| action when it completes. Pretty sure Dan Abramov taught
| this approach years ago in an egghead tutorial, if it takes
| hearing it from the horse's mouth to get you to consider
| not just throwing more libraries at it
| geraldwhen wrote:
| You need redux saga because api interactions can be complex.
|
| I need to update a remote resource. But wait! Sometimes that
| can fail. I need to capture the failure logic and make
| appropriate ui changes. There are 4 types of errors and they
| require doing some library logic to figure out what to
| display.
|
| But wait! I want to wait 250ms before triggering any state
| updates, or else the ui transitions will feel buggy.
|
| Oh, and product now wants to make sure we capture some random
| third party tracking event in between specific state changes.
| The ui MUST NOT change until the tracking call succeeds.
|
| This and more is trivial in redux saga, and you can write
| tests around it.
| weeksie wrote:
| Saga is so heavy and overly complex and you don't really
| get much out of it if you understand how middleware works.
| There's really no reason to add a huge dependency to your
| project.
|
| You can do all of that pretty easily with a vanilla redux.
| acemarke wrote:
| For the record, we actually have recommended _against_
| using sagas in most cases for a long time now, and
| especially for data fetching.
|
| Today, our recommendations are:
|
| - Data fetching: default to using RTK Query, fall back to
| thunks if needed
|
| - Responding to actions or state changes: use the new RTK
| "listener" middleware as the main approach
|
| See my recent talk "The Evolution of Redux Async Logic" for
| details:
|
| - https://blog.isquaredsoftware.com/2022/05/presentations-
| evol...
|
| as well as my recent presentation going through "Modern
| Redux with Redux Toolkit":
|
| - https://blog.isquaredsoftware.com/2022/06/presentations-
| mode...
| cageface wrote:
| I was called in to rescue a redux-saga based project that
| had gone badly off the rails. It was one of the worst
| codebases I've ever had to work with in many years of
| coding. Stack traces were useless and debugging with
| anything higher level than log statements was impossible.
| dboreham wrote:
| Apparently you don't need to debug if you're a good
| programmer. This explains why many modern tech stacks
| (JS, Scala, Kotlin, ...) have a horrible debugging
| experience.
| geraldwhen wrote:
| We specifically moved off thunks because the capricious
| whims of changing network calls with logic to support it
| is so much easier in redux saga. Stuff just works. You
| can handle every edge case.
|
| And now there are multiple deployed production apps with
| real users, so it's almost certainly never going to be
| replaced. The cost would be enormous.
| acemarke wrote:
| Yeah, I'm not questioning whether you _can_ do things
| with sagas, and there's definitely cases where their
| capabilities are valuable.
|
| But as I put it in my "Evolution" talk: "Sagas are like a
| chainsaw. Really powerful, and really dangerous. If you
| actually _need_ that power, great! But most of the time
| you don't actually _need_ to use a chainsaw on a daily
| basis."
|
| As the sibling comment said, a lot of times sagas really
| do end up as spaghetti code, largely because they are so
| event-driven, and with all the use of generator functions
| that can make debugging hard. (Ironically, the original
| Flux Architecture was created to _avoid_ the problems of
| Backbone-style event triggers causing events to ricochet
| around the app without a way to understand how things
| would update in response, and sagas can end up recreating
| that problem with Redux apps.)
| aidos wrote:
| Oh my. What is this ecosystem where the maintainers are
| downvoted for explaining the current recommendations for
| those using their library?
| russellpekala wrote:
| I do find redux super helpful for undo/redo (as mentioned in the
| article) and have not found a similar library for another state
| management solution that can do quite what I need there.
| melony wrote:
| Most of these new client side state management libraries are
| incompatible with any form of SSR. If you see the documentation
| for Jotai/Zustand/Valtio, the solution is to avoid using with
| Next.js at all, or fall back to hacks using context+provider at
| which point the state manager becomes effectively redundant.
| rebelos wrote:
| Isn't SSR only really relevant when you need to optimize for
| SEO (which only applies to a subset of apps)? Seems like it
| doesn't confer any other _significant_ benefit.
| azemetre wrote:
| Think about how the benefits to SEO (page speed, web vitals,
| less client work) can improve overall app performance.
|
| SSR is just one technique.
| purplerabbit wrote:
| I'm sorry people are downvoting, because you are correct.
|
| SSR (by which I mean Next.js) is the most over-invested in JS
| tech of all time. It introduces a bunch of crummy DX which
| never pays for itself from a business standpoint.
|
| SSR is only potentially useful for landing pages. In which
| case you should be using Wordpress or something like
| Wordpress so you aren't wasting dev resources on something a
| marketing team should be doing. (If your argument is that SSR
| is necessary for speed, I'm pretty sure exporting your
| Wordpress site to static HTML + CSS and using Cloudflare
| could more than make up for the difference.)
|
| The one asterisk I'll add to this is that SSR in the form of
| the Remix framework _may_ justify its own existence as it
| removes the need for an explicit API layer, which lets you
| skip a ton of boilerplate code. This is a big win. The fact
| that Remix uses SSR is just an implementation detail -- it 's
| the DX that's actually valuable (although SSR fetishists will
| probably still like it, too.)
| cosmiccatnap wrote:
| I find it interesting that across a decade and countless
| frameworks from jQuery, meteor, angular, and now react the core
| problem is still and somehow progressively worse than
| ever...state.
|
| I find it strange this is still such a hard problem to solve in
| an environment with a slew of options for key value global,
| local, and remote storage
| bayesian_horse wrote:
| It's easier to solve it than to agree on what is the solution
| and to keep it. The more alternatives to redux there are, the
| higher the chance you get thrown into projects with some lesser
| known framework, maybe not even used to its best.
| [deleted]
| meling wrote:
| I've not seen overmindjs mentioned on hacker news. We use it in
| our React app and my students who wrote the code liked it a
| lot... maybe others have advanced enough by now to be on par with
| or better than overmindjs.
|
| https://overmindjs.org/
| abxytg wrote:
| I've been running into nasty performance with setRecoilState and
| large piece of state firing multiple times per frame.
| rochak wrote:
| Has React become too big for people to not consider other
| alternatives? I used to be a big React advocate but realised that
| it is getting too bloated with every new release. Have been
| looking into Svelte and it is turning out to be a breath of fresh
| air compared to whatever React is culminating to be.
| sakerbos wrote:
| I've advocated for Redux in many commercial projects because I
| knew that it worked well at scale. There was occasional pushback
| due to the large amount of boilerplate code involved (actions,
| reducers, sagas, models/interfaces if using Typescript) but the
| team mostly settled on Redux because it was the best supported
| and most widely used state management framework at the time. IMO
| the larger pool of devs that understand a framework, the better a
| project's chances are of success mainly because the industry has
| a high turnover of developers and it's easier to find
| replacements to maintain the existing code.
|
| That being said, I'm now a huge fan of react-query.
| Yhippa wrote:
| Question for you since you seem knowledgeable about React state
| management. When I did a lot of back-end programming in Java we
| frequently coded to interfaces where we could swap out back-end
| implementations for ORM for example if needed. There's an
| ongoing joke where nobody actually did that.
|
| Is there something like that in React? My understanding is that
| there's a lot of coming and going of state management
| frameworks, and it would seem to me committing to thr API
| methods of a particular framework would be risky. Or am I
| thinking at the wrong abstraction level?
| acemarke wrote:
| To some extent, this was the purpose of the
| "container/presentational" pattern that was popular for a few
| years [0]. By splitting your components into "containers",
| which were responsible for managing data fetching, and
| "presentational" components, which just received data as
| props and displayed the UI, in theory you could swap out the
| state layer someday without having to alter most of the
| display handling.
|
| But, the community really began over-obsessing about that,
| and often treated it as a rule you _had_ to follow (to the
| point of people seeming to panic and asking for help about
| whether a particular component should live in a `/containers`
| folder, `/components`, or somewhere else).
|
| Dan Abramov, who wrote the article that helped really
| popularize that approach, later updated it to say he no
| longer finds it very useful.
|
| In addition, React hooks push you towards a very different
| approach, where each component is now responsible for calling
| the hooks that it relies on for data fetching. That hook may
| still abstract where the data actually comes from, but the
| calls are now part of the component itself. I talked about
| this change in approach in a blog post and conference talk
| conference talk [1] [2].
|
| Finally, the testing approaches in the ecosystem have changed
| as well. Instead of "shallow rendering" components using the
| Enzyme library, the community has moved on towards more
| "integration"-style tests with React Testing Library. This
| does require more setup work in tests to ensure you have all
| the various data providers wrapping the components under
| tests, and real or mock data being loaded, but the tests
| themselves become simpler and any state library usage becomes
| basically irrelevant to the actual test implementation. See
| [3] and [4] for some thoughts on that.
|
| Soooo... yes, you _can_ write more abstraction layers, split
| your components by "containers", and even add DI via React
| context or some other purpose-built library if you want to.
| You could even abstract out all the UI components you use
| from a particular library just in case you end up swapping
| date pickers or something. But as always, it's a question of
| whether that will actually provide a benefit, now or in the
| future. And in general, most React apps do not bother with
| those extra abstractions.
|
| [0] https://medium.com/@dan_abramov/smart-and-dumb-
| components-7c...
|
| [1] https://blog.isquaredsoftware.com/2019/07/blogged-
| answers-th...
|
| [2] https://blog.isquaredsoftware.com/2019/09/presentation-
| hooks...
|
| [3] https://kentcdodds.com/blog/testing-implementation-
| details
|
| [4] https://blog.isquaredsoftware.com/2021/06/the-evolution-
| of-r...
| jfvinueza wrote:
| I've been using Pullstate for medium-sized apps for a couple
| years and it's fantastic: uses Immer under the hood (so it's all
| immutable even if it look as it wasn't), it's API and mental
| model are vulgarly simple, and my impression is that it's quite
| performant. I also like that the store is disentangled from the
| component tree, which allows for plenty of flexibility. Totally
| recommended!
|
| https://lostpebble.github.io/pullstate/
| dageshi wrote:
| After reading the "Grug Developer" article recently, I've been
| thinking of frontend development as "The Plane of Eternal
| Complexity Demons".
| jitl wrote:
| This is because UI programming is inherently extremely complex,
| especially compared to something like a stateless API tier
| running in AWS. It's stateful software deployed to countless
| different runtimes on hardware you don't control. Instead of a
| smattering of API routes handling well-structured semantic
| datatypes like `POST /burgers?pickles=false`, input comes in
| the form of arbitrary UI events from various input devices like
| pens, keyboards, mice, etc that must be interpreted to have a
| semantic meaning. Often there are hundreds of API routes (event
| handling elements) on screen at once in a complex application.
| UI engineers are perpetually frustrated by this complexity, and
| so some small percentage look for better ways to handle these
| issues.
|
| Of course it's best to avoid UI programming entirely, but in
| many domains it's necessary.
| mllllv wrote:
| I disagree, I think UI programming is inherently quite
| simple. Especially with a paradigm like immediate-mode GUIs
| in my opinion. I believe the complexity comes from the fact
| that the DOM is a poor API for creating user interfaces,
| which ultimately inspired developers to create frameworks
| that work in a more "immediate-mode" style way.
| cageface wrote:
| The native UI toolkits are even harder to use than
| something like React and recently have been evolving to a
| similar reactive + declarative paradigm.
|
| User interfaces are complex, poorly specified, and subject
| to rapid and often capricious changes in the middle of
| development. Don't blame the tools.
| wizofaus wrote:
| There are definitely examples of UI programming that is more
| complex than certain APIs that largely perform basic CRUD
| operations, but I'd strongly disagree either is inherently
| more complex than the other, it's just that human behaviours
| and preferences are messy and unpredictable, which means
| conceptually "simple and elegant" UIs are often not what
| users actually enjoy using, and this inevitably has impacts
| at the code level. APIs don't have to designed to deal with
| human eccentricities as they're written for developers, and
| we aren't like normal people.
| aaaaaaaaaaab wrote:
| Bullshit. In 1995 people were creating desktop UIs order of
| magnitude more complex than today's anemic webapps, without
| any of the braindamage-inducing stuff that's happening in web
| UI development.
| ChefboyOG wrote:
| I was legitimately curious about this--my memory of Windows
| 95 is not this nice--so I looked at Wikipedia's list of
| software released in 1995:
|
| https://en.m.wikipedia.org/wiki/Category:1995_software
|
| What software specifically do you recall being "an order of
| magnitude more complex" than today's popular web apps?
| aaaaaaaaaaab wrote:
| Just from the top of my mind: Excel, Word, Photoshop,
| Windows Commander (called Total Commander today),
| SolidWorks, AutoCAD, Borland Delphi.
| nwh5jg56df wrote:
| We went to the moon some +50 years ago. We ought to have
| solved "UI programming" already, no?
|
| Something is not working
| syspec wrote:
| By that logo , SpaceX shouldn't exist.
| agumonkey wrote:
| simple problems easily becomes complex in mainstream
| contexts.. due to bazaar like soil. NASA had to solve one
| immensely hard problem but they owned the context. Vertical
| integration if you will.
| wly_cdgr wrote:
| UI programming is much harder than going to the moon. Do
| not confuse danger, scale, glamour, etc with difficulty
| bobthepanda wrote:
| Ultimately, successful products are determined by customers
| and by product managers and their executives, and it turns
| out there is no one-size-fits-all approach to even basic UI
| programming because everyone has an opinion.
|
| Not to mention, as an example touch became a widespread new
| UI paradigm in the last 10-20 years.
| robocat wrote:
| JavaScipt on the browser is cursed[1].
|
| 1. There is no standard GUI library, as per article. A GUI can
| be as arbitrarily complex as you wish, and every different
| frontend system is a unique GUI system deployed in JavaScript,
| usually using HTML for the view drawing primitives* and events
| for input. The complexities of GUI library design bubble up to
| developers who are implementing their own tweaks or
| combinations of a GUI library, usually with a huge amount of
| "needless" variation. Application developers should ideally
| never have to be making choices about internals of a GUI
| system, yet the core of most articles comparing frontend
| frameworks is discussing GUI internals.
|
| 2. There is no golden standard for tooling. Everyone has their
| pet variations on how to deploy to JavaScript, CSS, and HTML.
|
| 3. Back end choice. Huge variation.
|
| As a developer we get APIs on the edges, but we make our own
| spaghetti to join everything how we wish because there is not
| one or two standard library/framework choices, and we have the
| power to do what we will. I developed my own 100% custom
| component framework because I could write one that suited us
| far better than what was available at the time (OSS or
| commercial). Browser variation used to be a huge driver for
| complexity, but is far less so now.
|
| * drawing primitives can also be Canvas or SVG or WebGL e.g.
| https://news.ycombinator.com/item?id=27131659 is a good
| comment.
|
| [1] https://www.google.co.nz/search?q=lisp+curse
| Starlevel001 wrote:
| Server-side templating died for this.
| sph wrote:
| It makes me smile that elsewhere in this thread there's people
| saying "I've been using <library> and state management is now
| super easy." when you know in two months people will be saying
| that library is over-engineered and someone will suggest to try
| the new panacea that will solve all of your problems, for real
| this time.
|
| Such is the hype cycle of frontend development.
| jcelerier wrote:
| I mostly use Qt Widgets which hasn't fundamentally changed
| since 1995 and still performs just fine for desktop UI
| [deleted]
| doitLP wrote:
| Link: https://grugbrain.dev/
|
| It is universally worth your time to read it if you haven't :)
| maxekman wrote:
| Amazing read! Missed it when it trended 10 days ago.
|
| https://news.ycombinator.com/item?id=31840331
| pcthrowaway wrote:
| Plain english translation: https://github.com/reidjs/grug-
| dev-translation
|
| I haven't read it, but wish I had seen it before struggling
| through the original
| surrealize wrote:
| Thanks so much for the link! I tried the original and
| bounced off the style. It seemed like something that might
| be fun and useful if I invested enough effort in reading
| it, but I just bounced off.
|
| But with the translation, I just devoured and appreciated
| it.
| memonkey wrote:
| Absolutely great article. One thing I always see missing is why
| front-end applications can't use sessionStorage or localStorage?
| Why is this generally frowned upon?
| wizofaus wrote:
| I'd assume because it's often abused? There are perfectly
| legitimate reasons to use either and I've been technical lead
| on React projects where the decision was made to use them. In
| at least one case it was a known "shortcut" as we didn't have
| time to properly develop server-side persistence and local
| storage was "good enough" for 95% of use cases. And session
| storage is needed to allow page refreshes without cookies.
| bayesian_horse wrote:
| For what purpose? If you use it as state management inside the
| SPA, it's actually slower than all the other approaches.
___________________________________________________________________
(page generated 2022-07-02 23:00 UTC)