-
Notifications
You must be signed in to change notification settings - Fork 47.3k
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
Allow forms to skip hydration of hidden inputs #26735
Conversation
These config methods can already skip passed and it allows us to unify these into a single check.
This lets us reuse the nodeType check.
// Match | ||
if ( | ||
enableFormActions && | ||
type === 'input' && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could just go into the switch below if we didn't bother checking the inRootOrSingleton
context. Which probably makes sense since the other rules really apply to all context. It's just maybe worth for perf - especially checking isMarkedHoistable unnecessarily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah maybe we just ignore the root/singleton context. Questioning that in my other comment
I could argue that maybe we should just never throw in prod for extra nodes to simplify the rules and code. The main mechanism we rely on is actually text nodes anyway since we don't look at the attributes. Text nodes typically cover mistakes like keys or wrong cases not lining up in production. As long as we do find all nodes, it's at least possible to continue. |
Comparing: 540bab0...b2b497c Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: Expand to show |
4c5d6f4
to
04e4daa
Compare
This lets us put extra data to encode actions at the end.
Really this could be limited to just buttons but I just made it a general thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd approve except I think there is a (possibly pre-existing) bug with skipping past suspense nodes.
if (!inRootOrSingleton || !enableHostSingletons) { | ||
return null; | ||
} | ||
const nextInstance = getNextHydratableSibling(instance); | ||
if (nextInstance === null) { | ||
return null; | ||
} | ||
instance = nextInstance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be a flaw already but if the hydratable instance is a suspense node but we're trying to hydrate text and we're in the root or a singleton then we'll call getNextHydratableSibling on the comment node which is incorrect. If hydratable is a comment I think we need to return null here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the same time, does it matter? It's going to be a hydration error anyway, most likely, at least when the Suspense boundary doesn't find its node.
Arguably this is more resilient to non-suspense boundary comments that get inserted. I'm hesitant to "fix" it for that reason. Also, note that this is the same as the previous case. Only in inRootOrSingleton
scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense, marked approved
return ( | ||
(enableHostSingletons || | ||
(parentType !== 'head' && parentType !== 'body')) && | ||
(!enableFormActions || parentType !== 'form') | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is doing double duty as the signal for not clearing forms and as a signal to not clear head and body when singletons flag is turned off. We should make it two separate functions so it is clearer we can delete the legacy one once the singletons flag lands
element.getAttribute('title') !== | ||
(anyProps.title == null ? null : anyProps.title) | ||
if (element.nodeName.toLowerCase() !== type.toLowerCase()) { | ||
if (!inRootOrSingleton || !enableHostSingletons) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need the host singleton check here? with flag is off we always hit this branch and with it on we skip it at the root level (and at the singleton level) but practically speaking we'll never be at root or singleton level because we'll always be in a form when this counts.
Seems like we can avoid the check altogether and always verify based on nodeName === 'input' or we can just use the inRootOrSingleton check and rely on the fact that when singleton flag is off it turn into an inRoot check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was just an oversight before this PR that this code should've been just completely eliminated with the flag off. Basically there's no loop here without it since it always exists.
// Match | ||
if ( | ||
enableFormActions && | ||
type === 'input' && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah maybe we just ignore the root/singleton context. Questioning that in my other comment
Would that simplify much? the tail nodes thing is maybe easy to just apply all the time but could we get away with skipping extra elements in every context? I suppose you're considering Text and Suspense boundaries as anchors at that point Hmm maybe this is actually good. I kinda like the idea of consistent behavior and we can stop tracking scope |
This allows us to emit extra ephemeral data that will only be used on server rendered forms. First I refactored the shouldSkip functions to now just do that work inside the canHydrate methods. This makes the Config bindings a little less surface area but it also helps us optimize a bit since we now can look at the code together and find shared paths. canHydrate returns the instance if it matches, that used to just be there to refine the type but it can also be used to just return a different instance later that we find. If we don't find one, we'll bail out and error regardless so no need to skip past anything. DiffTrain build for [67f4fb0](67f4fb0)
…essive enhancement (#26749) Stacked on top of #26735. This allows a framework to add a `$$FORM_ACTION` property to a function. This lets the framework return a set of props to use in place of the function but only during SSR. Effectively, this lets you implement progressive enhancement of form actions using some other way instead of relying on the replay feature. This will be used by RSC on Server References automatically by convention in a follow up, but this mechanism can also be used by other frameworks/libraries.
…essive enhancement (#26749) Stacked on top of #26735. This allows a framework to add a `$$FORM_ACTION` property to a function. This lets the framework return a set of props to use in place of the function but only during SSR. Effectively, this lets you implement progressive enhancement of form actions using some other way instead of relying on the replay feature. This will be used by RSC on Server References automatically by convention in a follow up, but this mechanism can also be used by other frameworks/libraries. DiffTrain build for [559e83a](559e83a)
Includes the following upstream changes: - [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use content hash for react-native builds ([vercel#26734](facebook/react#26734)) (Samuel Susla) - [559e83aeb](https://github.com/facebook/react/commits/559e83aeb) [Fizz] Allow an action provide a custom set of props to use for progressive enhancement ([vercel#26749](facebook/react#26749)) (Sebastian Markbåge) - [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow forms to skip hydration of hidden inputs ([vercel#26735](facebook/react#26735)) (Sebastian Markbåge) - [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84) [Fizz] Encode external fizz runtime into chunks eagerly ([vercel#26752](facebook/react#26752)) (Josh Story) - [491aec5d6](https://github.com/facebook/react/commits/491aec5d6) Implement experimental_useOptimisticState ([vercel#26740](facebook/react#26740)) (Andrew Clark) - [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add nonce support to bootstrap scripts and external runtime ([vercel#26738](facebook/react#26738)) (Dan Ott) - [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate DevTools test to fix CI ([#26742](facebook/react#26742)) (Andrew Clark) - [b12bea62d](https://github.com/facebook/react/commits/b12bea62d) Preinits should support a nonce option ([#26744](facebook/react#26744)) (Josh Story) - [efbd68511](https://github.com/facebook/react/commits/efbd68511) Remove unused `initialStatus` parameter from `useHostTransitionStatus` ([vercel#26743](facebook/react#26743)) (Sebastian Silbermann) - [18282f881](https://github.com/facebook/react/commits/18282f881) Fix: Update while suspended fails to interrupt ([vercel#26739](facebook/react#26739)) (Andrew Clark) - [540bab085](https://github.com/facebook/react/commits/540bab085) Implement experimental_useFormStatus ([#26722](facebook/react#26722)) (Andrew Clark)
Includes the following upstream changes: - [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use content hash for react-native builds ([vercel#26734](facebook/react#26734)) (Samuel Susla) - [559e83aeb](https://github.com/facebook/react/commits/559e83aeb) [Fizz] Allow an action provide a custom set of props to use for progressive enhancement ([vercel#26749](facebook/react#26749)) (Sebastian Markbåge) - [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow forms to skip hydration of hidden inputs ([vercel#26735](facebook/react#26735)) (Sebastian Markbåge) - [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84) [Fizz] Encode external fizz runtime into chunks eagerly ([vercel#26752](facebook/react#26752)) (Josh Story) - [491aec5d6](https://github.com/facebook/react/commits/491aec5d6) Implement experimental_useOptimisticState ([vercel#26740](facebook/react#26740)) (Andrew Clark) - [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add nonce support to bootstrap scripts and external runtime ([vercel#26738](facebook/react#26738)) (Dan Ott) - [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate DevTools test to fix CI ([#26742](facebook/react#26742)) (Andrew Clark) - [b12bea62d](https://github.com/facebook/react/commits/b12bea62d) Preinits should support a nonce option ([#26744](facebook/react#26744)) (Josh Story) - [efbd68511](https://github.com/facebook/react/commits/efbd68511) Remove unused `initialStatus` parameter from `useHostTransitionStatus` ([vercel#26743](facebook/react#26743)) (Sebastian Silbermann) - [18282f881](https://github.com/facebook/react/commits/18282f881) Fix: Update while suspended fails to interrupt ([vercel#26739](facebook/react#26739)) (Andrew Clark) - [540bab085](https://github.com/facebook/react/commits/540bab085) Implement experimental_useFormStatus ([#26722](facebook/react#26722)) (Andrew Clark)
Includes the following upstream changes: - [b7972822b](https://github.com/facebook/react/commits/b7972822b) useOptimisticState -> useOptimistic ([#26772](facebook/react#26772)) (Andrew Clark) - [388686f29](https://github.com/facebook/react/commits/388686f29) Add "canary" to list of allowed npm dist tags ([#26767](facebook/react#26767)) (Andrew Clark) - [8a25302c6](https://github.com/facebook/react/commits/8a25302c6) fix[dynamic-scripts-injection]: unregister content scripts before registration ([#26765](facebook/react#26765)) (Ruslan Lesiutin) - [2c2476834](https://github.com/facebook/react/commits/2c2476834) Rename "next" prerelease channel to "canary" ([#26761](facebook/react#26761)) (Andrew Clark) - [fa4314841](https://github.com/facebook/react/commits/fa4314841) Remove deprecated workflow key from Circle config ([#26762](facebook/react#26762)) (Andrew Clark) - [5dd90c562](https://github.com/facebook/react/commits/5dd90c562) Use content hash for react-native builds ([#26734](facebook/react#26734)) (Samuel Susla) - [559e83aeb](https://github.com/facebook/react/commits/559e83aeb) [Fizz] Allow an action provide a custom set of props to use for progressive enhancement ([#26749](facebook/react#26749)) (Sebastian Markbåge) - [67f4fb021](https://github.com/facebook/react/commits/67f4fb021) Allow forms to skip hydration of hidden inputs ([#26735](facebook/react#26735)) (Sebastian Markbåge) - [8ea96ef84](https://github.com/facebook/react/commits/8ea96ef84) [Fizz] Encode external fizz runtime into chunks eagerly ([#26752](facebook/react#26752)) (Josh Story) - [491aec5d6](https://github.com/facebook/react/commits/491aec5d6) Implement experimental_useOptimisticState ([#26740](facebook/react#26740)) (Andrew Clark) - [9545e4810](https://github.com/facebook/react/commits/9545e4810) Add nonce support to bootstrap scripts and external runtime ([#26738](facebook/react#26738)) (Dan Ott) - [86b0e9199](https://github.com/facebook/react/commits/86b0e9199) Gate DevTools test to fix CI ([#26742](facebook/react#26742)) (Andrew Clark) - [b12bea62d](https://github.com/facebook/react/commits/b12bea62d) Preinits should support a nonce option ([#26744](facebook/react#26744)) (Josh Story) - [efbd68511](https://github.com/facebook/react/commits/efbd68511) Remove unused `initialStatus` parameter from `useHostTransitionStatus` ([#26743](facebook/react#26743)) (Sebastian Silbermann) - [18282f881](https://github.com/facebook/react/commits/18282f881) Fix: Update while suspended fails to interrupt ([#26739](facebook/react#26739)) (Andrew Clark) - [540bab085](https://github.com/facebook/react/commits/540bab085) Implement experimental_useFormStatus ([#26722](facebook/react#26722)) (Andrew Clark) ---------
This allows us to emit extra ephemeral data that will only be used on server rendered forms. First I refactored the shouldSkip functions to now just do that work inside the canHydrate methods. This makes the Config bindings a little less surface area but it also helps us optimize a bit since we now can look at the code together and find shared paths. canHydrate returns the instance if it matches, that used to just be there to refine the type but it can also be used to just return a different instance later that we find. If we don't find one, we'll bail out and error regardless so no need to skip past anything.
…essive enhancement (facebook#26749) Stacked on top of facebook#26735. This allows a framework to add a `$$FORM_ACTION` property to a function. This lets the framework return a set of props to use in place of the function but only during SSR. Effectively, this lets you implement progressive enhancement of form actions using some other way instead of relying on the replay feature. This will be used by RSC on Server References automatically by convention in a follow up, but this mechanism can also be used by other frameworks/libraries.
This allows us to emit extra ephemeral data that will only be used on server rendered forms. First I refactored the shouldSkip functions to now just do that work inside the canHydrate methods. This makes the Config bindings a little less surface area but it also helps us optimize a bit since we now can look at the code together and find shared paths. canHydrate returns the instance if it matches, that used to just be there to refine the type but it can also be used to just return a different instance later that we find. If we don't find one, we'll bail out and error regardless so no need to skip past anything. DiffTrain build for commit 67f4fb0.
…essive enhancement (#26749) Stacked on top of #26735. This allows a framework to add a `$$FORM_ACTION` property to a function. This lets the framework return a set of props to use in place of the function but only during SSR. Effectively, this lets you implement progressive enhancement of form actions using some other way instead of relying on the replay feature. This will be used by RSC on Server References automatically by convention in a follow up, but this mechanism can also be used by other frameworks/libraries. DiffTrain build for commit 559e83a.
This allows us to emit extra ephemeral data that will only be used on server rendered forms.
First I refactored the shouldSkip functions to now just do that work inside the canHydrate methods. This makes the Config bindings a little less surface area but it also helps us optimize a bit since we now can look at the code together and find shared paths.
canHydrate returns the instance if it matches, that used to just be there to refine the type but it can also be used to just return a different instance later that we find. If we don't find one, we'll bail out and error regardless so no need to skip past anything.