[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)