Earlier quoted context omitted.
ELI5 why Excel can update all of the sheets from all the different data sources without overloading its user with “state management” thing and React can not?
This talk from Rich Harris should answer most of your Qs: Rethinking reactivity https://www.youtube.com/watch?v=AdNJ3fydeao He goes over the history of spreadsheets, reactive programming, and dunks on react.
The new wave of React state management
271–280 of 310 posts
Re: The new wave of React state management
#272Earlier quoted context omitted.
You may consider using some “schedule re-render everything at the next animation frame after an event” type of library instead.
I do have something like that but it mostly triggers every frame anyway due to so many things being updated. With that said, do you know any libraries like that?
Re: The new wave of React state management
#273Earlier quoted context omitted.
Frankly I feel state management is a difficult task on desktop apps as well, to the point that tracking spaghetti-shaped causation and control flow is beyond my mental abilities. Qt itself as well as many apps are rife with redundantly calculating state or redrawing GUIs when changing the same value multiple times, or changing two values which both affect an outcome (my StateTransaction pattern mostly alleviates this…
I haven't worked with Qt so I don't know how the API looks, But on a complex app, to see "dirty bitflags", "intermediate values", "redrew the UI in the middle of mutating document state", I feel what you feel, and I want to share what helps me and my team overcome this kind of complexity. This happened a few years ago to my team. We alleviated this with several solutions. The most effective solutions is to 1.) separa…
Re: The new wave of React state management
#274Earlier quoted context omitted.
ELI5 why Excel can update all of the sheets from all the different data sources without overloading its user with “state management” thing and React can not?
This talk from Rich Harris should answer most of your Qs: Rethinking reactivity https://www.youtube.com/watch?v=AdNJ3fydeao He goes over the history of spreadsheets, reactive programming, and dunks on react.
It answers my question only tangentially, because it doesn’t touch state management per se. The key point was, what’s the fuss about React SM and why it must be explicit in it. The video basically says that it is a nonsense which may and should be avoided. I agree, and so still don’t get what ggp is talking about.
Re: The new wave of React state management
#275Earlier quoted context omitted.
I haven't worked with Qt so I don't know how the API looks, But on a complex app, to see "dirty bitflags", "intermediate values", "redrew the UI in the middle of mutating document state", I feel what you feel, and I want to share what helps me and my team overcome this kind of complexity. This happened a few years ago to my team. We alleviated this with several solutions. The most effective solutions is to 1.) separa…
You're probably going to seriously confuse someone familiar with the "actor pattern". Look it up.
This "thing" is partially influenced by actor pattern. The other influences are entity component system and Alan Kay's original of OOP.
Re: The new wave of React state management
#276Earlier quoted context omitted.
I haven't worked with Qt so I don't know how the API looks, But on a complex app, to see "dirty bitflags", "intermediate values", "redrew the UI in the middle of mutating document state", I feel what you feel, and I want to share what helps me and my team overcome this kind of complexity. This happened a few years ago to my team. We alleviated this with several solutions. The most effective solutions is to 1.) separa…
Sorry, I don't understand what you're getting at. When timers or user actions are triggered, what code runs, where is the state it modifies located (next to the specific timer/action, within a module or dialog's object, or globally), how does the function determine which parts of the UI to reload from state, and when does it reload the UI? (Is this explained in the video or not? I haven't watched it yet.)
Before we got into where state should be and when is UI reload/rerender triggered. I'm going to tell you a little imaginary problem.
Imagine you are building an application for downloading several huge files.
1.) This app must have a download page to trigger the downloading of various files as well as monitor their statuses.
2.) a system to manage multiple downloads. It can queue multiple downloads but only one should run at a time. But, regardless of the download page is open or not, the downloader should run its download.
3.) a persistent notification system for the app to notify the user (e.g. if a download succeeded or failed). This notification should be persisting, meaning that if the user does not dismiss a notification, it will stay there. The UI for the notification system looks like a smart phone's one.
4.) There are several other pages in the app.
Before we got into asking where state should be placed, we should examine what actors are there. There are the "downloader", the "download page", the "notification system", the "notification UI".
Because we have these several actors, we need to assume that all of these have several local states. All of these actors need to be in the component tree, but not necessarily bound to the rendering lifecycle.
The dependency arrows look like this:
- "download page"=>"downloader"=>"notification system" - "notification UI" => "notification system"
These dependency arrows form the component tree automatically. Now, let's examine the solution:
- The state that tracks the notification should be in the notification system. The user-facing message in a notification item should be a copy that is put into the memory of the notification system.
- The state that tracks the queue of multiple downloads and the function that schedule the downloads should live in the downloader. These scheduler will have its own timer-like mechanism to notify itself that it needs to run other task if one is finished.
- The download page "listens" to events and "borrows" data from the "downloader". So if the downloader makes a change, the downloader page will change too.
- Last, the notification UI. The notification UI lives longer than the download page, because the user can switch between page but the notification UI stays on. The notification UI listens to the notification system for changes in its state and borrows its state.
- If you pay attention to the dependency arrow, notification UI and and download page both are the descendant of the notification system, but only notification UI react to "change-signal" from the notification system. Download page should not react to any signal from notification UI (e.g. no rerender).
- This is an indicator that the notification system must not be bound into the re-render lifecycle of the tree of components. Notification UI should explicitly subscribe to the notification system in order to allow other page to ignore the notification system. In JavaScript/TypeScript it is pretty easy to implement a callback-based event emitter that can be attached/detached.
- The notification system and the downloader is what I call an actor that can, but not always, be bound into the render lifecycle. It lives with the component that spawns and destroy it, but is detached from it.
Re: The new wave of React state management
#277For 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…
React Query's critical design flaw (from when I used it, anyway), is that data is scoped globally by default, as opposed to per mount. Using the global cache is kind of the point, yes, but that's implicitly the case and that's the exact opposite of how useState works. I think that is an egregious mistake, since it is totally unclear to a higher level consumer that this is the case. This may seem unreasonable, but I'v…
And having it behave differently from useState is fine, and correct. The library is used to fetch data, not state. Those are two different things
Re: The new wave of React state management
#278Earlier quoted context omitted.
It's a great benefit for a component to be able to specify what data it needs from remote without worrying about if an ancestor or sibling also needed it. React query will only fetch once the unique queries in the whole tree. Without this feature, every component needing remote data D must share a parent ancestor fetching D for all of them, even when the children are not conceptually related. Adding another component…
> must share a parent ancestor fetching D for all of them What happened to the whole "service" pattern? Isn't this the core problem it solved for Java in the 90's?
Re: The new wave of React state management
#279Earlier quoted context omitted.
React Query's critical design flaw (from when I used it, anyway), is that data is scoped globally by default, as opposed to per mount. Using the global cache is kind of the point, yes, but that's implicitly the case and that's the exact opposite of how useState works. I think that is an egregious mistake, since it is totally unclear to a higher level consumer that this is the case. This may seem unreasonable, but I'v…
Nothing implicit about react query caching requests. That's the whole point of the library in the first place, otherwise it would just be a fetch wrapper. And having it behave differently from useState is fine, and correct. The library is used to fetch data, not state. Those are two different things
I like its query and request primitives, but I don't like that they are coupled to the cache.
Re: The new wave of React state management
#280Earlier quoted context omitted.
React Query's critical design flaw (from when I used it, anyway), is that data is scoped globally by default, as opposed to per mount. Using the global cache is kind of the point, yes, but that's implicitly the case and that's the exact opposite of how useState works. I think that is an egregious mistake, since it is totally unclear to a higher level consumer that this is the case. This may seem unreasonable, but I'v…
data is scoped globally by default, as opposed to per mount. Uh, is the cache key the same? To me it is 100% clear that the cache key is used for a global cache, and that this is one of the core design principles of the library. This global cache management is exactly what I desire over useState without writing my own boilerplate.
I ended up having to do this myself by wrapping it all up and providing an option for the caller to opt-in to the underlying global key. If the option was not passed, it would append a unique ID to the base key by default so it would become scoped to the particular mount.
IMO that should be the default behaviour.