-
Notifications
You must be signed in to change notification settings - Fork 46.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Idea: forceDeepUpdate() and forceDeepUpdateWithScope(scope) #7759
Comments
@sebmarkbage Sorry if this is naive but what is |
@developit It is some kind of user provided tuple. It can be anything that we can implement an equality check on I guess. I'd expect it to be something like |
I need this for hot reloading too. |
I cannot agree with this concept in general, but localization is a good example. Scoping for updates can be done with immutable state (new reference on proper level). Everything should by pass by props, but I don't want to add locale to all interfaces and repeat assignment. For localization, I use global field (window._currentCulture) and when language is changed I call _.deepClone() (from lodash lib) on main state (in store), forcing all components to refresh. I'm not proud of it, but this is my workaround (only for this situation). I'm curious how you deal with it? |
Intuitively wouldn't that be to introduce a new life-cycle method that is called before next render after So in the end there would be 3 ways of passing data, which would basically exists on an axis;
All three have their strength and weaknesses, but each with use-cases where they are the best solution to the problem. EDIT: I would go so far as to say that explicitly passing e.g. |
@syranide That's an interesting idea to put this in state. I was thinking that we could also have a different API like |
@sebmarkbage I didn't really think too deeply about state vs data, was mainly trying to keep it simple for the discussion. But yeah, I mean it is fundamentally props, just a different way of getting them, so if you also have a life-cycle method like As a thought experiment; what if data AND contexts were all merged into props. So you would have a single interface to get your props, regardless of source, you could then override globals with contexts, and contexts with props. Practically you would need to specify these "bridges" explicitly, i.e. "expose |
Hi, any update on this? |
If there are updates they will be on this issue 😉 |
Seems like we went with this as an alternative. reactjs/rfcs#2 |
Just going to put it out there for feedback...
Motivation
Subscription management comes with a cost and that eats into the wins of async rendering since it needs to be managed synchronously. Not just managing the direct subscriptions themselves but managing the dynamic dependency graph so that it can be invalidated.
Meanwhile, most of what subscriptions are used for is data that will never update. At least in our apps. It is a pure loss.
The use case is when you're connecting to third party systems that aren't as easily connected to the top level data tree.
Proposal
Same use case as
forceUpdate
, if you are reading from global mutable state for some reason, you can use this to by-passshouldComponentUpdate
in an entire subtree. Basically rerender everything. When combined with Fiber this can be a low-priority update so it's not so bad for things that change a lot of things.A good example would be changing the locale. Regardless if you read a global mutable locale (like AirBnB does) or a context locale (like Yahoo) does, this lets you change it when you need to. Without needing to manage subscriptions for all those cases when you don't need it.
forceDeepUpdateWithScope
would traverse the subtree and only start rendering ifshouldComponentUpdateForScope
returnstrue
for the arbitraryscope
argument. This allows for a bit more of a targeted update with some convenience overhead.Additionally, React would cache the pair of
scope
andcomponents
that responded. For some number of scopes back. If a new component gets mounted with ashouldComponentUpdateForScope
we might check it against the cache to see if we need to add it to the cache.Effectively this creates lazy subscriptions.
The use case is something like typing into an input field that then updates some global store which immediately displays in a completely different place on the page. The first character might be a bit slower but still with responsive levels and the subsequent characters are fast to update.
Caveat
The major downside of this proposal is that it relies on mutation. As we know, React doesn't really like mutation for many more reasons than just
shouldComponentUpdate
.The effect in Fiber for example, is that any component that gets a higher priority update will start using the new value. Components that rely on mutable state effectively become up-prioritized which is not good. 1) It can temporarily show inconsistent data. 2) The point of making this kind of update lower priority is because it is likely to be large. Larger updates will stall the page if they take the same priority as higher priority updates. Thereby defeating the benefits of Fiber anyway.
I'd like to try to come up with a variant of this API that doesn't rely on mutation.
The text was updated successfully, but these errors were encountered: