mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Rethrow errors from form actions (#26689)
This is the next step toward full support for async form actions. Errors thrown inside form actions should cause the form to re-render and throw the error so it can be captured by an error boundary. The behavior is the same if the `<form />` had an internal useTransition hook, which is pretty much exactly how we implement it, too. The first time an action is called, the form's HostComponent is "upgraded" to become stateful, by lazily mounting a list of hooks. The rest of the implementation for function components can be shared. Because the error handling behavior added in this commit is just using useTransition under-the-hood, it also handles pending states, too. However, this pending state can't be observed until we add a new hook for that purpose. I'll add this next. DiffTrain build for commit https://github.com/facebook/react/commit/fd3fb8e3c5d1c977f4bfa73d715143804c69d4b0.
This commit is contained in:
+12
-2
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<a8437bee4ca7ca2a6e95eed698390cea>>
|
||||
* @generated SignedSource<<968b9a9a87595c8009c33efb698508af>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -21437,6 +21437,16 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
break;
|
||||
}
|
||||
|
||||
case HostComponent: {
|
||||
// Some host components are stateful (that's how we implement form
|
||||
// actions) but we don't bother to reuse the memoized state because it's
|
||||
// not worth the extra code. The main reason to reuse the previous hooks
|
||||
// is to reuse uncached promises, but we happen to know that the only
|
||||
// promises that a host component might suspend on are definitely cached
|
||||
// because they are controlled by us. So don't bother.
|
||||
resetHooksOnUnwind(); // Fallthrough to the next branch.
|
||||
}
|
||||
|
||||
default: {
|
||||
// Other types besides function components are reset completely before
|
||||
// being replayed. Currently this only happens when a Usable type is
|
||||
@@ -23838,7 +23848,7 @@ function createFiberRoot(
|
||||
return root;
|
||||
}
|
||||
|
||||
var ReactVersion = "18.3.0-next-c57a0f68a-20230421";
|
||||
var ReactVersion = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
// Might add PROFILE later.
|
||||
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<4f902d10ff6c4c49a6f2e765b4662a5e>>
|
||||
* @generated SignedSource<<3dd5e105138064b59966612a35ec1f24>>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -6973,6 +6973,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -8599,7 +8601,7 @@ var devToolsConfig$jscomp$inline_1021 = {
|
||||
throw Error("TestRenderer does not support findFiberByHostInstance()");
|
||||
},
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-test-renderer"
|
||||
};
|
||||
var internals$jscomp$inline_1206 = {
|
||||
@@ -8630,7 +8632,7 @@ var internals$jscomp$inline_1206 = {
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
};
|
||||
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
||||
var hook$jscomp$inline_1207 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<7b0d73bfc531dfd6dc0711c8a343756d>>
|
||||
* @generated SignedSource<<778f87e6da120be9b98db0d06274b299>>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -7324,6 +7324,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -9025,7 +9027,7 @@ var devToolsConfig$jscomp$inline_1063 = {
|
||||
throw Error("TestRenderer does not support findFiberByHostInstance()");
|
||||
},
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-test-renderer"
|
||||
};
|
||||
var internals$jscomp$inline_1247 = {
|
||||
@@ -9056,7 +9058,7 @@ var internals$jscomp$inline_1247 = {
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
};
|
||||
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
||||
var hook$jscomp$inline_1248 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ if (
|
||||
}
|
||||
"use strict";
|
||||
|
||||
var ReactVersion = "18.3.0-next-c57a0f68a-20230421";
|
||||
var ReactVersion = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
// ATTENTION
|
||||
// When adding new symbols to this file,
|
||||
|
||||
+1
-1
@@ -639,4 +639,4 @@ exports.useSyncExternalStore = function (
|
||||
);
|
||||
};
|
||||
exports.useTransition = useTransition;
|
||||
exports.version = "18.3.0-next-c57a0f68a-20230421";
|
||||
exports.version = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ exports.useSyncExternalStore = function (
|
||||
);
|
||||
};
|
||||
exports.useTransition = useTransition;
|
||||
exports.version = "18.3.0-next-c57a0f68a-20230421";
|
||||
exports.version = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
|
||||
if (
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
c57a0f68a49d0a7fbe45e7b28820478d0fa4e32f
|
||||
fd3fb8e3c5d1c977f4bfa73d715143804c69d4b0
|
||||
|
||||
+12
-2
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<40e2743803d8d937ee642c7e74254e74>>
|
||||
* @generated SignedSource<<b3b5a76440bc189cfbc25945472cc0ca>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -24609,6 +24609,16 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
break;
|
||||
}
|
||||
|
||||
case HostComponent: {
|
||||
// Some host components are stateful (that's how we implement form
|
||||
// actions) but we don't bother to reuse the memoized state because it's
|
||||
// not worth the extra code. The main reason to reuse the previous hooks
|
||||
// is to reuse uncached promises, but we happen to know that the only
|
||||
// promises that a host component might suspend on are definitely cached
|
||||
// because they are controlled by us. So don't bother.
|
||||
resetHooksOnUnwind(); // Fallthrough to the next branch.
|
||||
}
|
||||
|
||||
default: {
|
||||
// Other types besides function components are reset completely before
|
||||
// being replayed. Currently this only happens when a Usable type is
|
||||
@@ -27148,7 +27158,7 @@ function createFiberRoot(
|
||||
return root;
|
||||
}
|
||||
|
||||
var ReactVersion = "18.3.0-next-c57a0f68a-20230421";
|
||||
var ReactVersion = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
function createPortal$1(
|
||||
children,
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<472cb7f28d742af2e290a0816a880f33>>
|
||||
* @generated SignedSource<<388ecd5d71ee2c3022a43487fedc6a5a>>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -8063,6 +8063,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -9470,7 +9472,7 @@ var roots = new Map(),
|
||||
devToolsConfig$jscomp$inline_1045 = {
|
||||
findFiberByHostInstance: getInstanceFromNode,
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-native-renderer",
|
||||
rendererConfig: {
|
||||
getInspectorDataForViewTag: function () {
|
||||
@@ -9512,7 +9514,7 @@ var internals$jscomp$inline_1276 = {
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
};
|
||||
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
||||
var hook$jscomp$inline_1277 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<eb589f3defe98e20e791e57446c3f979>>
|
||||
* @generated SignedSource<<8e8a7cd3892f3b9331677bf16ba6a24b>>
|
||||
*/
|
||||
|
||||
|
||||
@@ -8660,6 +8660,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -10179,7 +10181,7 @@ var roots = new Map(),
|
||||
devToolsConfig$jscomp$inline_1123 = {
|
||||
findFiberByHostInstance: getInstanceFromNode,
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-native-renderer",
|
||||
rendererConfig: {
|
||||
getInspectorDataForViewTag: function () {
|
||||
@@ -10234,7 +10236,7 @@ var roots = new Map(),
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
});
|
||||
exports.createPortal = function (children, containerTag) {
|
||||
return createPortal$1(
|
||||
|
||||
+12
-2
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<36dfe2e6840704492b6fbf0d00f5b91a>>
|
||||
* @generated SignedSource<<6a9f3cb903b49266953a4dde78ca03fb>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -25122,6 +25122,16 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
break;
|
||||
}
|
||||
|
||||
case HostComponent: {
|
||||
// Some host components are stateful (that's how we implement form
|
||||
// actions) but we don't bother to reuse the memoized state because it's
|
||||
// not worth the extra code. The main reason to reuse the previous hooks
|
||||
// is to reuse uncached promises, but we happen to know that the only
|
||||
// promises that a host component might suspend on are definitely cached
|
||||
// because they are controlled by us. So don't bother.
|
||||
resetHooksOnUnwind(); // Fallthrough to the next branch.
|
||||
}
|
||||
|
||||
default: {
|
||||
// Other types besides function components are reset completely before
|
||||
// being replayed. Currently this only happens when a Usable type is
|
||||
@@ -27661,7 +27671,7 @@ function createFiberRoot(
|
||||
return root;
|
||||
}
|
||||
|
||||
var ReactVersion = "18.3.0-next-c57a0f68a-20230421";
|
||||
var ReactVersion = "18.3.0-next-fd3fb8e3c-20230421";
|
||||
|
||||
function createPortal$1(
|
||||
children,
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<54d01cff9e9c78ffba08f73a6631a077>>
|
||||
* @generated SignedSource<<04b313069e799ea7f158cb3281fe8365>>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -8315,6 +8315,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -9729,7 +9731,7 @@ var roots = new Map(),
|
||||
devToolsConfig$jscomp$inline_1100 = {
|
||||
findFiberByHostInstance: getInstanceFromTag,
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-native-renderer",
|
||||
rendererConfig: {
|
||||
getInspectorDataForViewTag: function () {
|
||||
@@ -9771,7 +9773,7 @@ var internals$jscomp$inline_1345 = {
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
};
|
||||
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
||||
var hook$jscomp$inline_1346 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
|
||||
+5
-3
@@ -7,7 +7,7 @@
|
||||
* @noflow
|
||||
* @nolint
|
||||
* @preventMunge
|
||||
* @generated SignedSource<<1ac72a305be24eff51144b88fe9c565d>>
|
||||
* @generated SignedSource<<9b14144dbccddb7d3273b95ff3f77a1c>>
|
||||
*/
|
||||
|
||||
|
||||
@@ -8912,6 +8912,8 @@ function replaySuspendedUnitOfWork(unitOfWork) {
|
||||
workInProgressRootRenderLanes
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
resetHooksOnUnwind();
|
||||
default:
|
||||
unwindInterruptedWork(current, unitOfWork),
|
||||
(unitOfWork = workInProgress =
|
||||
@@ -10438,7 +10440,7 @@ var roots = new Map(),
|
||||
devToolsConfig$jscomp$inline_1178 = {
|
||||
findFiberByHostInstance: getInstanceFromTag,
|
||||
bundleType: 0,
|
||||
version: "18.3.0-next-c57a0f68a-20230421",
|
||||
version: "18.3.0-next-fd3fb8e3c-20230421",
|
||||
rendererPackageName: "react-native-renderer",
|
||||
rendererConfig: {
|
||||
getInspectorDataForViewTag: function () {
|
||||
@@ -10493,7 +10495,7 @@ var roots = new Map(),
|
||||
scheduleRoot: null,
|
||||
setRefreshHandler: null,
|
||||
getCurrentFiber: null,
|
||||
reconcilerVersion: "18.3.0-next-c57a0f68a-20230421"
|
||||
reconcilerVersion: "18.3.0-next-fd3fb8e3c-20230421"
|
||||
});
|
||||
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
|
||||
computeComponentStackForErrorReporting: function (reactTag) {
|
||||
|
||||
Reference in New Issue
Block a user