Skip to content

Commit fc5a146

Browse files
committed
useFormState: Reuse state from previous form submission (#27321)
If a Server Action is passed to useFormState, the action may be submitted before it has hydrated. This will trigger a full page (MPA-style) navigation. We can transfer the form state to the next page by comparing the key path of the hook instance. `ReactServerDOMServer.decodeFormState` is used by the server to extract the form state from the submitted action. This value can then be passed as an option when rendering the new page. It must be passed during both SSR and hydration. ```js const boundAction = await decodeAction(formData, serverManifest); const result = await boundAction(); const formState = decodeFormState(result, formData, serverManifest); // SSR const response = createFromReadableStream(<App />); const ssrStream = await renderToReadableStream(response, { formState }) // Hydration hydrateRoot(container, <App />, { formState }); ``` If the `formState` option is omitted, then the state won't be transferred to the next page. However, it must be passed in both places, or in neither; misconfiguring will result in a hydration mismatch. (The `formState` option is currently prefixed with `experimental_`) DiffTrain build for commit 612b2b6.
1 parent 419e64c commit fc5a146

File tree

13 files changed

+122
-83
lines changed

13 files changed

+122
-83
lines changed

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<cd445f3b30b95bc14ba23cb28c191840>>
10+
* @generated SignedSource<<90d4b49133c0f3de327f45d0812fd8e9>>
1111
*/
1212

1313
'use strict';
@@ -23883,7 +23883,8 @@ function FiberRootNode(
2388323883
tag,
2388423884
hydrate,
2388523885
identifierPrefix,
23886-
onRecoverableError
23886+
onRecoverableError,
23887+
formState
2388723888
) {
2388823889
this.tag = tag;
2388923890
this.containerInfo = containerInfo;
@@ -23917,6 +23918,7 @@ function FiberRootNode(
2391723918
this.pooledCacheLanes = NoLanes;
2391823919
}
2391923920

23921+
this.formState = formState;
2392023922
this.incompleteTransitions = new Map();
2392123923

2392223924
{
@@ -23950,15 +23952,17 @@ function createFiberRoot(
2395023952
// single type, like a DynamicHostConfig that is defined by the renderer.
2395123953
identifierPrefix,
2395223954
onRecoverableError,
23953-
transitionCallbacks
23955+
transitionCallbacks,
23956+
formState
2395423957
) {
2395523958
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
2395623959
var root = new FiberRootNode(
2395723960
containerInfo,
2395823961
tag,
2395923962
hydrate,
2396023963
identifierPrefix,
23961-
onRecoverableError
23964+
onRecoverableError,
23965+
formState
2396223966
);
2396323967
// stateNode is any.
2396423968

@@ -23994,7 +23998,7 @@ function createFiberRoot(
2399423998
return root;
2399523999
}
2399624000

23997-
var ReactVersion = "18.3.0-canary-e5205658f-20230913";
24001+
var ReactVersion = "18.3.0-canary-612b2b660-20230913";
2399824002

2399924003
// Might add PROFILE later.
2400024004

@@ -24044,7 +24048,9 @@ function createContainer(
2404424048
isStrictMode,
2404524049
concurrentUpdatesByDefaultOverride,
2404624050
identifierPrefix,
24047-
onRecoverableError
24051+
onRecoverableError,
24052+
transitionCallbacks,
24053+
null
2404824054
);
2404924055
}
2405024056
function updateContainer(element, container, parentComponent, callback) {
@@ -24911,7 +24917,8 @@ function create(element, options) {
2491124917
isStrictMode,
2491224918
concurrentUpdatesByDefault,
2491324919
"",
24914-
onRecoverableError
24920+
onRecoverableError,
24921+
null
2491524922
);
2491624923

2491724924
if (root == null) {

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<d1b32810e51fc98372bfbb5c93420bef>>
10+
* @generated SignedSource<<5361a5f040398d7d166b0f13b30a010c>>
1111
*/
1212

1313
"use strict";
@@ -8179,7 +8179,8 @@ function FiberRootNode(
81798179
tag,
81808180
hydrate,
81818181
identifierPrefix,
8182-
onRecoverableError
8182+
onRecoverableError,
8183+
formState
81838184
) {
81848185
this.tag = tag;
81858186
this.containerInfo = containerInfo;
@@ -8212,6 +8213,7 @@ function FiberRootNode(
82128213
this.onRecoverableError = onRecoverableError;
82138214
this.pooledCache = null;
82148215
this.pooledCacheLanes = 0;
8216+
this.formState = formState;
82158217
this.incompleteTransitions = new Map();
82168218
}
82178219
function createContainer(
@@ -8228,7 +8230,8 @@ function createContainer(
82288230
tag,
82298231
!1,
82308232
identifierPrefix,
8231-
onRecoverableError
8233+
onRecoverableError,
8234+
null
82328235
);
82338236
1 === tag
82348237
? ((tag = 1),
@@ -8612,19 +8615,19 @@ function wrapFiber(fiber) {
86128615
fiberToWrapper.set(fiber, wrapper));
86138616
return wrapper;
86148617
}
8615-
var devToolsConfig$jscomp$inline_1027 = {
8618+
var devToolsConfig$jscomp$inline_1028 = {
86168619
findFiberByHostInstance: function () {
86178620
throw Error("TestRenderer does not support findFiberByHostInstance()");
86188621
},
86198622
bundleType: 0,
8620-
version: "18.3.0-canary-e5205658f-20230913",
8623+
version: "18.3.0-canary-612b2b660-20230913",
86218624
rendererPackageName: "react-test-renderer"
86228625
};
8623-
var internals$jscomp$inline_1226 = {
8624-
bundleType: devToolsConfig$jscomp$inline_1027.bundleType,
8625-
version: devToolsConfig$jscomp$inline_1027.version,
8626-
rendererPackageName: devToolsConfig$jscomp$inline_1027.rendererPackageName,
8627-
rendererConfig: devToolsConfig$jscomp$inline_1027.rendererConfig,
8626+
var internals$jscomp$inline_1227 = {
8627+
bundleType: devToolsConfig$jscomp$inline_1028.bundleType,
8628+
version: devToolsConfig$jscomp$inline_1028.version,
8629+
rendererPackageName: devToolsConfig$jscomp$inline_1028.rendererPackageName,
8630+
rendererConfig: devToolsConfig$jscomp$inline_1028.rendererConfig,
86288631
overrideHookState: null,
86298632
overrideHookStateDeletePath: null,
86308633
overrideHookStateRenamePath: null,
@@ -8641,26 +8644,26 @@ var internals$jscomp$inline_1226 = {
86418644
return null === fiber ? null : fiber.stateNode;
86428645
},
86438646
findFiberByHostInstance:
8644-
devToolsConfig$jscomp$inline_1027.findFiberByHostInstance ||
8647+
devToolsConfig$jscomp$inline_1028.findFiberByHostInstance ||
86458648
emptyFindFiberByHostInstance,
86468649
findHostInstancesForRefresh: null,
86478650
scheduleRefresh: null,
86488651
scheduleRoot: null,
86498652
setRefreshHandler: null,
86508653
getCurrentFiber: null,
8651-
reconcilerVersion: "18.3.0-canary-e5205658f-20230913"
8654+
reconcilerVersion: "18.3.0-canary-612b2b660-20230913"
86528655
};
86538656
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
8654-
var hook$jscomp$inline_1227 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
8657+
var hook$jscomp$inline_1228 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
86558658
if (
8656-
!hook$jscomp$inline_1227.isDisabled &&
8657-
hook$jscomp$inline_1227.supportsFiber
8659+
!hook$jscomp$inline_1228.isDisabled &&
8660+
hook$jscomp$inline_1228.supportsFiber
86588661
)
86598662
try {
8660-
(rendererID = hook$jscomp$inline_1227.inject(
8661-
internals$jscomp$inline_1226
8663+
(rendererID = hook$jscomp$inline_1228.inject(
8664+
internals$jscomp$inline_1227
86628665
)),
8663-
(injectedHook = hook$jscomp$inline_1227);
8666+
(injectedHook = hook$jscomp$inline_1228);
86648667
} catch (err) {}
86658668
}
86668669
exports._Scheduler = Scheduler;
@@ -8691,7 +8694,8 @@ exports.create = function (element, options) {
86918694
isStrictMode,
86928695
concurrentUpdatesByDefault,
86938696
"",
8694-
onRecoverableError
8697+
onRecoverableError,
8698+
null
86958699
);
86968700
if (null == root) throw Error("something went wrong");
86978701
updateContainer(element, root, null, null);

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<c0a54e40c38caf663b646a4c7f7321d1>>
10+
* @generated SignedSource<<486546c05387fd5f0f9d0c9c12aa9b75>>
1111
*/
1212

1313
"use strict";
@@ -8603,7 +8603,8 @@ function FiberRootNode(
86038603
tag,
86048604
hydrate,
86058605
identifierPrefix,
8606-
onRecoverableError
8606+
onRecoverableError,
8607+
formState
86078608
) {
86088609
this.tag = tag;
86098610
this.containerInfo = containerInfo;
@@ -8636,6 +8637,7 @@ function FiberRootNode(
86368637
this.onRecoverableError = onRecoverableError;
86378638
this.pooledCache = null;
86388639
this.pooledCacheLanes = 0;
8640+
this.formState = formState;
86398641
this.incompleteTransitions = new Map();
86408642
this.passiveEffectDuration = this.effectDuration = 0;
86418643
}
@@ -8653,7 +8655,8 @@ function createContainer(
86538655
tag,
86548656
!1,
86558657
identifierPrefix,
8656-
onRecoverableError
8658+
onRecoverableError,
8659+
null
86578660
);
86588661
1 === tag
86598662
? ((tag = 1),
@@ -9038,19 +9041,19 @@ function wrapFiber(fiber) {
90389041
fiberToWrapper.set(fiber, wrapper));
90399042
return wrapper;
90409043
}
9041-
var devToolsConfig$jscomp$inline_1069 = {
9044+
var devToolsConfig$jscomp$inline_1070 = {
90429045
findFiberByHostInstance: function () {
90439046
throw Error("TestRenderer does not support findFiberByHostInstance()");
90449047
},
90459048
bundleType: 0,
9046-
version: "18.3.0-canary-e5205658f-20230913",
9049+
version: "18.3.0-canary-612b2b660-20230913",
90479050
rendererPackageName: "react-test-renderer"
90489051
};
9049-
var internals$jscomp$inline_1267 = {
9050-
bundleType: devToolsConfig$jscomp$inline_1069.bundleType,
9051-
version: devToolsConfig$jscomp$inline_1069.version,
9052-
rendererPackageName: devToolsConfig$jscomp$inline_1069.rendererPackageName,
9053-
rendererConfig: devToolsConfig$jscomp$inline_1069.rendererConfig,
9052+
var internals$jscomp$inline_1268 = {
9053+
bundleType: devToolsConfig$jscomp$inline_1070.bundleType,
9054+
version: devToolsConfig$jscomp$inline_1070.version,
9055+
rendererPackageName: devToolsConfig$jscomp$inline_1070.rendererPackageName,
9056+
rendererConfig: devToolsConfig$jscomp$inline_1070.rendererConfig,
90549057
overrideHookState: null,
90559058
overrideHookStateDeletePath: null,
90569059
overrideHookStateRenamePath: null,
@@ -9067,26 +9070,26 @@ var internals$jscomp$inline_1267 = {
90679070
return null === fiber ? null : fiber.stateNode;
90689071
},
90699072
findFiberByHostInstance:
9070-
devToolsConfig$jscomp$inline_1069.findFiberByHostInstance ||
9073+
devToolsConfig$jscomp$inline_1070.findFiberByHostInstance ||
90719074
emptyFindFiberByHostInstance,
90729075
findHostInstancesForRefresh: null,
90739076
scheduleRefresh: null,
90749077
scheduleRoot: null,
90759078
setRefreshHandler: null,
90769079
getCurrentFiber: null,
9077-
reconcilerVersion: "18.3.0-canary-e5205658f-20230913"
9080+
reconcilerVersion: "18.3.0-canary-612b2b660-20230913"
90789081
};
90799082
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
9080-
var hook$jscomp$inline_1268 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
9083+
var hook$jscomp$inline_1269 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
90819084
if (
9082-
!hook$jscomp$inline_1268.isDisabled &&
9083-
hook$jscomp$inline_1268.supportsFiber
9085+
!hook$jscomp$inline_1269.isDisabled &&
9086+
hook$jscomp$inline_1269.supportsFiber
90849087
)
90859088
try {
9086-
(rendererID = hook$jscomp$inline_1268.inject(
9087-
internals$jscomp$inline_1267
9089+
(rendererID = hook$jscomp$inline_1269.inject(
9090+
internals$jscomp$inline_1268
90889091
)),
9089-
(injectedHook = hook$jscomp$inline_1268);
9092+
(injectedHook = hook$jscomp$inline_1269);
90909093
} catch (err) {}
90919094
}
90929095
exports._Scheduler = Scheduler;
@@ -9117,7 +9120,8 @@ exports.create = function (element, options) {
91179120
isStrictMode,
91189121
concurrentUpdatesByDefault,
91199122
"",
9120-
onRecoverableError
9123+
onRecoverableError,
9124+
null
91219125
);
91229126
if (null == root) throw Error("something went wrong");
91239127
updateContainer(element, root, null, null);

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (
2727
}
2828
"use strict";
2929

30-
var ReactVersion = "18.3.0-canary-e5205658f-20230913";
30+
var ReactVersion = "18.3.0-canary-612b2b660-20230913";
3131

3232
// ATTENTION
3333
// When adding new symbols to this file,

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-prod.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,4 @@ exports.useSyncExternalStore = function (
616616
exports.useTransition = function () {
617617
return ReactCurrentDispatcher.current.useTransition();
618618
};
619-
exports.version = "18.3.0-canary-e5205658f-20230913";
619+
exports.version = "18.3.0-canary-612b2b660-20230913";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-profiling.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ exports.useSyncExternalStore = function (
619619
exports.useTransition = function () {
620620
return ReactCurrentDispatcher.current.useTransition();
621621
};
622-
exports.version = "18.3.0-canary-e5205658f-20230913";
622+
exports.version = "18.3.0-canary-612b2b660-20230913";
623623

624624
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
625625
if (
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e5205658f40ad181279857dbb66e36b8ebcd8c0e
1+
612b2b6601abb844248c384d1e288bb824b180b7

compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<588595e62718a973abbe3ee5129ccaa8>>
10+
* @generated SignedSource<<01008a8950368c139ee32158a8728c5d>>
1111
*/
1212

1313
'use strict';
@@ -26929,7 +26929,8 @@ function FiberRootNode(
2692926929
tag,
2693026930
hydrate,
2693126931
identifierPrefix,
26932-
onRecoverableError
26932+
onRecoverableError,
26933+
formState
2693326934
) {
2693426935
this.tag = tag;
2693526936
this.containerInfo = containerInfo;
@@ -26958,6 +26959,7 @@ function FiberRootNode(
2695826959
this.identifierPrefix = identifierPrefix;
2695926960
this.onRecoverableError = onRecoverableError;
2696026961

26962+
this.formState = formState;
2696126963
this.incompleteTransitions = new Map();
2696226964

2696326965
{
@@ -27000,15 +27002,17 @@ function createFiberRoot(
2700027002
// single type, like a DynamicHostConfig that is defined by the renderer.
2700127003
identifierPrefix,
2700227004
onRecoverableError,
27003-
transitionCallbacks
27005+
transitionCallbacks,
27006+
formState
2700427007
) {
2700527008
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
2700627009
var root = new FiberRootNode(
2700727010
containerInfo,
2700827011
tag,
2700927012
hydrate,
2701027013
identifierPrefix,
27011-
onRecoverableError
27014+
onRecoverableError,
27015+
formState
2701227016
);
2701327017
// stateNode is any.
2701427018

@@ -27033,7 +27037,7 @@ function createFiberRoot(
2703327037
return root;
2703427038
}
2703527039

27036-
var ReactVersion = "18.3.0-canary-8ee3c01f";
27040+
var ReactVersion = "18.3.0-canary-f73f8a34";
2703727041

2703827042
function createPortal$1(
2703927043
children,
@@ -27177,7 +27181,9 @@ function createContainer(
2717727181
isStrictMode,
2717827182
concurrentUpdatesByDefaultOverride,
2717927183
identifierPrefix,
27180-
onRecoverableError
27184+
onRecoverableError,
27185+
transitionCallbacks,
27186+
null
2718127187
);
2718227188
}
2718327189
function updateContainer(element, container, parentComponent, callback) {
@@ -28005,7 +28011,8 @@ function render(element, containerTag, callback, concurrentRoot) {
2800528011
false,
2800628012
null,
2800728013
"",
28008-
onRecoverableError
28014+
onRecoverableError,
28015+
null
2800928016
);
2801028017
roots.set(containerTag, root);
2801128018
}

0 commit comments

Comments
 (0)