facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
229.31k stars 46.96k forks source link

Recursive forceUpdate #3038

Closed tgriesser closed 9 years ago

tgriesser commented 9 years ago

It would be nice if there were a way to call forceUpdate in a way that it would be applied recursively to children elements. I'm currently using shouldComponentUpdate paired with Immutable.js in a similar fashion to OM and I've found that this behavior can be preferable in some cases.

One concrete use case would be @gaearon's hot loader - which currently attempts to gather all of the elements and trigger a forceUpdate but it seems to still somehow be hitting shouldComponentUpdate in my application (haven't quite tracked down where/how).

Another use case would be as a simple solution to #2517 (the context / shouldComponentUpdate issue), when a context is changed you'd want to be able to forceUpdate on the element and all children.

gaearon commented 9 years ago

Unfortunately this wouldn't help me because I still need to walk the tree to auto-bind hot-patched methods.

it seems to still somehow be hitting shouldComponentUpdate in my application (haven't quite tracked down where/how).

Should not be the case, I specifically checked for this. If you can put up a reproducible example, I can take a look.

slorber commented 9 years ago

I also use something akin to Om, my state is completely outside of React in a single js-based Atom. Everything is always re-rendered from the very top in a pure functional way.

I want to be able to hot swap the user language, and to retranslate the React app in the target locale without having to refresh the whole html page.

I use React-intl which uses context.

I would be OK with a recursive forceUpdate of the top component on locale change.

Related: https://github.com/yahoo/react-intl/issues/58 https://github.com/facebook/react/issues/2517

slorber commented 9 years ago

Note that I have tested to unmount and remount the top-level node with the updated context.

What I can see is that if you unmount and remount the node in the same "event loop tick", visually it looks like a recursive forceUpdate: the component is not unmounted but simply rerendered from a fresh vdom (i guess).

It seems this behavior is constant when unmounting/remounting in same event loop, and can also appear (randomly) when a setTimeout 0 is introduced.

tgriesser commented 9 years ago

Never mind, I realized this can be accomplished quite easily by just setting the key to a unique value wherever you wish to remount the entire tree.

slorber commented 9 years ago

nice trick to know @tgriesser thanks

mlarcher commented 8 years ago

Quite useful, thanks @tgriesser

gaearon commented 8 years ago

Never mind, I realized this can be accomplished quite easily by just setting the key to a unique value wherever you wish to remount the entire tree.

This would destroy the existing DOM though.

wmertens commented 8 years ago

How about, when you change the context, walking all your children with React.Children.forEach and calling forceUpdate on them if they have their contextTypes set to your context element?

If that works I think it would be neat if React had a helper function that did this. Screen size changes, translations, global edit mode, … all kinds of seldom-changing things that benefit from being on context.

jimfb commented 8 years ago

@wmertens React.Children.forEach returns elements (not components) so you can't call forceUpdate. Regardless, the OP already linked the relevant issue (#2517).

gaearon commented 8 years ago

FWIW I maintain https://github.com/gaearon/react-deep-force-update for my hot reloading purposes but it relies on React internals.

wmertens commented 8 years ago

Ok, for now I'll just stick to the safe side and continue using redux for data that would be better stored in context. Sometimes that means I have 50 of store listeners on the page but luckily that doesn't seem to impact performance for my use cases.

langpavel commented 7 years ago

Hi!

At first, I'm aware of @gaearon's react-deep-force-update but it seems it doesn't work on production build.

What I'm trying to solve is live retranslation of my page including re-executing router on feature/react-intl branch of react-starter-kit

What I'm worrying about is when I use @tgriesser's trick I can loose internal state of components (controlled or uncontrolled inputs...) I don't try the trick but I'm expecting that it can be too :bug: tricky for production..

Best if #2517 will be resolved and react-intl will be updated, but what I can do in meantime? May be I'm just doing something wrong...

wmertens commented 7 years ago

Pavel, you can use react-deep-force-update in production, just don't do it very often. Switching languages is what I use it for too. Give it a child reference and it will force-update the tree while retaining state, much better than force-re-rendering the whole tree.

It's magical, exactly what changing an attribute of the context object should do by default in React.

On Wed, May 24, 2017, 2:07 AM Pavel Lang notifications@github.com wrote:

Hi!

At first, I'm aware about @gaearon https://github.com/gaearon's react-deep-force-update but it seems it doesn't work on production build.

What I'm trying to solve is live retranslation of my page including re-executing router on feature/react-intl branch of react-starter-kit

What I'm worrying about is when I use @tgriesser https://github.com/tgriesser's trick I can loose internal state of components (controlled or uncontrolled inputs...) I don't try the trick but I'm expecting that it can be too 🐛 tricky for production..

Best if #2517 https://github.com/facebook/react/issues/2517 will be resolved and react-intl will be updated, but what I can do in meantime? May be I'm just doing something wrong...

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/facebook/react/issues/3038#issuecomment-303569245, or mute the thread https://github.com/notifications/unsubscribe-auth/AADWlk9ZzuSlnvGeWxb2HpPLLKwfNHpfks5r83DMgaJpZM4DbwKT .

wmertens commented 7 years ago

Note that I have a PR open on react-deep-force-update to only update components that subscribe to a certain context element, but it's languishing.

This would be the ideal out-of-the-box behavior for me. This allow choosing between event listeners and force-update-subscribers to pass updates down the tree.

On Wed, 24 May 2017, 11:13 AM Wout Mertens, wout.mertens@gmail.com wrote:

Pavel, you can use react-deep-force-update in production, just don't do it very often. Switching languages is what I use it for too. Give it a child reference and it will force-update the tree while retaining state, much better than force-re-rendering the whole tree.

It's magical, exactly what changing an attribute of the context object should do by default in React.

On Wed, May 24, 2017, 2:07 AM Pavel Lang notifications@github.com wrote:

Hi!

At first, I'm aware about @gaearon https://github.com/gaearon's react-deep-force-update but it seems it doesn't work on production build.

What I'm trying to solve is live retranslation of my page including re-executing router on feature/react-intl branch of react-starter-kit

What I'm worrying about is when I use @tgriesser https://github.com/tgriesser's trick I can loose internal state of components (controlled or uncontrolled inputs...) I don't try the trick but I'm expecting that it can be too 🐛 tricky for production..

Best if #2517 https://github.com/facebook/react/issues/2517 will be resolved and react-intl will be updated, but what I can do in meantime? May be I'm just doing something wrong...

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/facebook/react/issues/3038#issuecomment-303569245, or mute the thread https://github.com/notifications/unsubscribe-auth/AADWlk9ZzuSlnvGeWxb2HpPLLKwfNHpfks5r83DMgaJpZM4DbwKT .

gaearon commented 7 years ago

We'll likely get back to this. There's another issue about forceDeepUpdate where it is tracked.