We have an object graph (updated via web socket subscriptions) and then twist and turn slices of that data on the way up to the components. I hardly think about the fact that mobx is there and instead just think in terms of reshaping data for display.
Success with MobX on a project. I worked as lead picking up an existing code base - none of us had any MobX experience so came in fresh.
My employer was kind enough to offer up FrontendMasters subscriptions - I watched a MobX course there over a couple of nights - link: https://frontendmasters.com/courses/redux-mobx/
I enjoyed it! Got the job done, no scaling issues
We’re using redux (with a copious amount of selectors) and it’s the only reason I have a little bit of confidence where all our data is.
Now I could be wetting but it's hard to have these sorts of discussions on the abstract.
Can you name examples of such state?
I don't get the hesitation to use redux. I've used it on every single FE app I've worked on and never regretted it. I can make redux do exactly what I want it to do and with the power we get from memoization of selectors via reselect, there really is nothing that beats it.
I'm also convinced that most people praising react-query are hugely missing out on the level of control you get with redux. Further, coupling side-effects -- e.g. fetching data from api -- with react component lifecycles is wrought with awkward edge-cases that you don't have to deal with in redux.
Maybe I'm just not smart enough, but I've been working with Redux for a few months and I get more confused every time I look at it, despite hours of videos and documentation and tutorials. It's just not at all clear to me what it's doing behind the scenes and how the typings get transfered and what's happening during async operations.
I don't think I'd ever want to use Redux again after this experience. I'd much rather deal with performance problems than the layers of unreadable abstractions that Redux uses...
I also heavily leverage https://github.com/neurosnap/robodux to treat redux as a database.
At the end of the day, redux is an event emitter (pub/sub) with a single object that stores all of your state that multiple components need to reuse.
If you haven't seen RTK, we designed it to make Redux a lot simpler to learn and use:
- https://redux.js.org/introduction/why-rtk-is-redux-today
- https://redux.js.org/tutorials/essentials/part-2-app-structu...
- https://blog.isquaredsoftware.com/2022/06/presentations-mode...
Does memoizing the state help?
It doesn't. Updating state in a component triggers the re-rendering of all its children. This is what they are referring to. You can stop that propagating effect as usual by wrapping direct descendants in React.memo().
Be aware, that an anonymous list of components will show up as "re-rendering" in the browser tools. You can verify that this is not(!) the case by looking at the profiler instead.
Additionally, if you cannot tolerate even just one component re-rendering, you can simply use React.useSynExternalStore() instead of Context.
Not that with just react contexts, you can chose to split them up instead of or in addition to employing memoization
Context does not trigger the re-rendering of all children. Updating state does. And you prevent that propagating effect by wrapping direct descendants in React.memo().
React Router moved to contexts some number of versions ago...as I look into libraries for React, I see most leveraging Contexts. I've had success with it over the past year and appreciate your affirmation
Redux is nice, but it’s be nice to have a very minimal framework for adding a global and local states via hooks and syncing their data structures to the indexed db
It’s just rare enough that “prefer contexts” is a good rule. Simpler, easier to understand code, with no Redux nonsense.
- https://redux.js.org/tutorials/essentials/part-2-app-structu...
- https://redux.js.org/tutorials/typescript-quick-start#define...
I had senior developers, who have worked with RTK before, misusing simple features such as the "createSlice" API.
By contrast, I have never once sat down with a junior to walk through React's Context. I assume, they just read the docs and were good to go.
FWIW I see folks misusing / misunderstanding Context on a near-daily basis, mostly around misunderstanding what components will re-render and when. That's part of what led me to write my "Guide to React Rendering Behavior" post, to clarify when/why/how React renders:
- https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...
I've read your blog post, and I might be missing something, but you do not seem to be highlighting any re-rendering issues specific to context. Juniors will have to learn how React works anyway. Context or not.
- Thinking that if you change a field in the context value only components that read that field will re-render
- Thinking that _only_ the components that consume the context will re-render, not realizing that normal recursive rendering behavior resumes from there
- Not realizing that updating a context requires a `setState` call in the parent that renders the `<MyContext.Provider>`, and you can easily end up in a situation where the _entire_ component tree renders just because of default recursive rendering
Can you point to some examples of the "useless nesting" and "weird constructs" you're referring to? I'm curious to see what's happening, and if there's any docs improvements we can add to help provide guidance.
> Can you point to some examples of the "useless nesting" and "weird constructs" you're referring to?
Example: Create a slice with a list of items as initial state and truncate it in a reducer.
- Redux is cool but there’s so much decoupling that it gets hard to read the code. New hires would take too long to start, TS types got crazy, it was too much.
- XState is very good for state machines… but you barely ever need that level of control. Most of the time understanding it ends up being overhead. We’ve had maybe one good case for using it in about 10 years.
- React’s contexts are minimum overhead and work very well with “jump to definition” functionality and TS types. You can choose to use a reducer if you want, or skip it if it isn’t appropriate.
YMMV of course. This is just us.