mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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:
+39
-3
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user