6 ms·
Principal eng working with 3 teams on a ~500k loc React site here. After lots of experimentation, we’re just using React contexts. - Redux is cool but there’s
by wotamRobin 4y ago
Principal eng working with 3 teams on a ~500k loc React site here. After lots of experimentation, we’re just using React contexts.
- Redux is cool but there’s so much decoupling that it gets hard to read the code. New hires would take too long to start, TS types got crazy, it was too much.
- XState is very good for state machines… but you barely ever need that level of control. Most of the time understanding it ends up being overhead. We’ve had maybe one good case for using it in about 10 years.
- React’s contexts are minimum overhead and work very well with “jump to definition” functionality and TS types. You can choose to use a reducer if you want, or skip it if it isn’t appropriate.
YMMV of course. This is just us.
- shukantpal 4y agoWhat are your thoughts on MobX?
- aidos 4y agoWe use mobx and I think it’s great. The observable / computed model is really familiar from spreadsheets so it’s very easy to reason about code and computations. You always just think about your data in terms of being computed from dependencies without worrying about pushing state though the system. We have an object graph (updated via web socket subscriptions) and then twist and turn slices of that data on the way up to the components. I hardly think about the fact that mobx is there and instead just think in terms of reshaping data for display.
- ledauphin 4y agoi like mobx because it encourages you to separate state from presentation more than React Context does, but doesn't discourage keeping logically separate state trees separate the way Redux does.
- dcchuck 4y agoOther poster here - 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/ https://frontendmasters.com/courses/redux-mobx/ I enjoyed it! Got the job done, no scaling issues
- sircastor 4y agoI came into a fairly complex app using redux. I asked the developer about why contexts wouldn’t be a better fit, and within a week we’d dropped redux for contexts. There are certainly uses where Redux really is the right tool, but it’s nice how flexible the built in stuff is.
- Aeolun 4y agoWhat do you do for modifying the data that is shared across the app? It seems like you’d either have one huge context that’s very hard to manipulate, or many deeply nested small ones? We’re using redux (with a copious amount of selectors) and it’s the only reason I have a little bit of confidence where all our data is.
- arnorhs 4y agoI have built a lot of apps, including huge react apps. The problem you are describing is usually a result of people representing too much in state of as part of the same state. Now I could be wetting but it's hard to have these sorts of discussions on the abstract. Can you name examples of such state?
- valand 4y agoIt can be combinations of both. Many deeply nested small ones is convenient for objects/actors/agents/entities with different lifetimes.
- solardev 4y agoYou can have many small states within a larger context, and each consumer component can choose which states it wants from the context. Basically it's a bunch of global variables.
- yawnr 4y agoRight but every time that context changes it triggers a re-render of every child component regardless of if it’s consuming that bit of state or not. These comments are making me really question other peoples’ understanding of what I thought were kind of basic principles of how react, context, or redux work…
- deleted 4y ago[deleted]
- qudat 4y agoAgreed. For large apps with even a little bit of complexity, context doesn't seem like much of a solution. You either have a million contexts for every shared state slice to optimize re-renders or you have a single context that takes a huge hit on performance. A single large context object is redux except redux knows how to intelligently update components based on what changed. 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.
- chaimsalzer 4y agoNo issues with needless rerenders?
- yawnr 4y agoMy takeaway from these comments is that people either don’t care or literally don’t know how context works but are talking about how it’s better than redux lol
- mikojan 4y agoThis is your brain on Redux. 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().
- yawnr 4y agoGuess what, this entire thread is literally people discussing using context for… app state. But yeah thanks for being patronizing
- dmak 4y agoCould you elaborate?
- solardev 4y agoHe's probably talking about this thread... https://news.ycombinator.com/item?id=34134290 https://news.ycombinator.com/item?id=34134290
- symlinkk 4y agoI thought the issue with that is that it re-renders if any part of the context changes.
- yawnr 4y agoYou’re correct and these people advocating for this are definitely re-rendering every component in their tree with every change
- dmak 4y agoIt just means you need more granular contexts right?
- symlinkk 4y agoRight, but then you have a ton of contexts littered everywhere. Seems like that would be a lot of clutter.
- gnomewrecker 4y agoIn my experience most of my state in contexts changes infrequently (auth information, or the “current client” for a dashboard, or whatever), and then local state is sufficient for the rest. The few times I have sufficiently complexity in the “middle” I indeed have been annoyed and had to be careful to avoid over-frequent rerenders. It’s just rare enough that “prefer contexts” is a good rule. Simpler, easier to understand code, with no Redux nonsense.
- yawnr 4y agoRedux isn’t nonsense you’re just being dismissive and not taking the time to learn to understand it properly.
- dcchuck 4y agoThanks for sharing 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
- edgyquant 4y agoYep when I was rewriting the MVP at my current place I looked into them all and decided that context + hooks (and a server side pass for first paint) was all we needed. It was hairy at first keeping things in store etc but we wrote some lib functions that we haven’t had to touch since. 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
- solarkraft 4y agoGot any comment on the re-rendering argument? "Renders should be cheap anyway" or are you doing some specific optimizations?
- yawnr 4y agoFWIW I think hooks have made types a lot easier to deal with in Redux.
- acemarke 4y agoAbsolutely, and that's a major reason why we specifically teach the React-Redux hooks API as default today, and have guidance on setting up "pre-typed" hooks with the store types baked in: - https://redux.js.org/tutorials/essentials/part-2-app-structure#the-react-counter-component https://redux.js.org/tutorials/essentials/part-2-app-structu... - https://redux.js.org/tutorials/typescript-quick-start#define-typed-hooks https://redux.js.org/tutorials/typescript-quick-start#define...
- dandigangi 4y agoMoved to context in full also but I will say Redux's toolkit thing they released is a nice addition that was much needed. I do enjoy using some RxJS still for certain problems. Agreed on XState. Want to use it but its way overdoing it often.
- ricardobayes 4y agoSure, but as a senior I could get juniors up to speed on redux mostly within a day, the longest was 3 days. It's not that difficult if you have a working codebase they need to contribute to.
- mikojan 4y agoThis is not my experience at all. 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.
- acemarke 4y agoI'm genuinely curious - do you have any examples of "misusing `createSlice`"? 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-mostly-complete-guide-to-react-rendering-behavior/ https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...
- mikojan 4y agoA common issue with "createSlice" even with seasoned developers is they're introducing useless nesting and weird imperative-functional constructs because they fundamentally do not understand how "immer" works. 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.
- acemarke 4y agoThe usual misunderstandings about context are: - 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.