useFormState: Only emit markers if postback state is provided (#27374)
This is an optimization where useFormState will only emit extra comment markers if a form state is passed at the root. If no state is passed, we don't need to emit anything because none of the hooks will match.
Andrew Clark committed
Sep 14, 2023 at 11:46 UTC
d6dcad6a8beaeec0513a9851d1e0fe1181932360
2 files changed
+13
-9
packages/react-reconciler/src/ReactFiberHooks.js
+10
-5
@@ -2015,13 +2015,18 @@ function mountFormState<S, P>(
2015
): [S, (P) => void] {
2016
let initialState = initialStateProp;
2017
if (getIsHydrating()) {
2018
- const isMatching = tryToClaimNextHydratableFormMarkerInstance(
2019
- currentlyRenderingFiber,
2020
- );
2018
const root: FiberRoot = (getWorkInProgressRoot(): any);
2019
const ssrFormState = root.formState;
2023
- if (ssrFormState !== null && isMatching) {
2024
- initialState = ssrFormState[0];
2020
+ // If a formState option was passed to the root, there are form state
2021
+ // markers that we need to hydrate. These indicate whether the form state
2022
+ // matches this hook instance.
2023
+ if (ssrFormState !== null) {
2024
+ const isMatching = tryToClaimNextHydratableFormMarkerInstance(
2025
+ currentlyRenderingFiber,
2026
+ );
2027
+ if (isMatching) {
2028
+ initialState = ssrFormState[0];
2029
+ }
2030
}
2031
}
2032
const initialStateThenable: Thenable<S> = {
packages/react-server/src/ReactFizzServer.js
+3
-4
@@ -1193,11 +1193,10 @@ function finishFunctionComponent(
1193
formStateMatchingIndex: number,
1194
) {
1195
let didEmitFormStateMarkers = false;
1196
- if (formStateCount !== 0) {
1196
+ if (formStateCount !== 0 && request.formState !== null) {
1197
// For each useFormState hook, emit a marker that indicates whether we
1198
- // rendered using the form state passed at the root.
1199
- // TODO: As an optimization, Fizz should only emit these markers if form
1200
- // state is passed at the root.
1198
+ // rendered using the form state passed at the root. We only emit these
1199
+ // markers if form state is passed at the root.
1200
const segment = task.blockedSegment;
1201
if (segment === null) {
1202
// Implies we're in reumable mode.