Add on(Caught|Uncaught|Recoverable) opts to RN (#28836)

## Overview

There's currently a bug in RN now that we no longer re-throw errors. The
`showErrorDialog` function in React Native only logs the errors as soft
errors, and never a fatal. RN was depending on the global handler for
the fatal error handling and logging.

Instead of fixing this in `ReactFiberErrorDialog`, we can implement the
new root options in RN to handle caught/uncaught/recoverable in the
respective functions, and delete ReactFiberErrorDialog. I'll follow up
with a RN PR to implement these options and fix the error handling.
This commit is contained in:
Ricky
2024-04-15 12:03:28 -04:00
committed by GitHub
parent c113503ad1
commit 0347fcd007
2 changed files with 78 additions and 6 deletions
+39 -3
View File
@@ -101,11 +101,30 @@ function nativeOnCaughtError(
defaultOnCaughtError(error, errorInfo);
}
type NativeRenderOptions = {
onUncaughtError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onCaughtError?: (
error: mixed,
errorInfo: {
+componentStack?: ?string,
+errorBoundary?: ?React$Component<any, any>,
},
) => void,
onRecoverableError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
};
function render(
element: Element<ElementType>,
containerTag: number,
callback: ?() => void,
concurrentRoot: ?boolean,
options?: NativeRenderOptions,
): ?ElementRef<ElementType> {
if (disableLegacyMode && !concurrentRoot) {
throw new Error('render: Unsupported Legacy Mode API.');
@@ -114,6 +133,23 @@ function render(
let root = roots.get(containerTag);
if (!root) {
// TODO: these defaults are for backwards compatibility.
// Once RN implements these options internally,
// we can remove the defaults and ReactFiberErrorDialog.
let onUncaughtError = nativeOnUncaughtError;
let onCaughtError = nativeOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
if (options && options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}
if (options && options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}
if (options && options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
root = createContainer(
@@ -123,9 +159,9 @@ function render(
false,
null,
'',
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
onUncaughtError,
onCaughtError,
onRecoverableError,
null,
);
roots.set(containerTag, root);
+39 -3
View File
@@ -106,10 +106,29 @@ function nativeOnCaughtError(
defaultOnCaughtError(error, errorInfo);
}
type NativeRenderOptions = {
onUncaughtError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
onCaughtError?: (
error: mixed,
errorInfo: {
+componentStack?: ?string,
+errorBoundary?: ?React$Component<any, any>,
},
) => void,
onRecoverableError?: (
error: mixed,
errorInfo: {+componentStack?: ?string},
) => void,
};
function render(
element: Element<ElementType>,
containerTag: number,
callback: ?() => void,
options?: NativeRenderOptions,
): ?ElementRef<ElementType> {
if (disableLegacyMode) {
throw new Error('render: Unsupported Legacy Mode API.');
@@ -118,6 +137,23 @@ function render(
let root = roots.get(containerTag);
if (!root) {
// TODO: these defaults are for backwards compatibility.
// Once RN implements these options internally,
// we can remove the defaults and ReactFiberErrorDialog.
let onUncaughtError = nativeOnUncaughtError;
let onCaughtError = nativeOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
if (options && options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}
if (options && options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}
if (options && options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
}
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
root = createContainer(
@@ -127,9 +163,9 @@ function render(
false,
null,
'',
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
onUncaughtError,
onCaughtError,
onRecoverableError,
null,
);
roots.set(containerTag, root);