diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
index 4d8e677e03739..225d3657e0469 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
@@ -92,7 +92,7 @@ describe('ReactDOMFizzServer', () => {
function expectErrors(errorsArr, toBeDevArr, toBeProdArr) {
const mappedErrows = errorsArr.map(({error, errorInfo}) => {
const stack = errorInfo && errorInfo.componentStack;
- const digest = errorInfo && errorInfo.digest;
+ const digest = error.digest;
if (stack) {
return [error.message, digest, normalizeCodeLocInfo(stack)];
} else if (digest) {
@@ -3230,6 +3230,47 @@ describe('ReactDOMFizzServer', () => {
);
});
+ it('warns in dev if you access digest from errorInfo in onRecoverableError', async () => {
+ await act(async () => {
+ const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
+
,
+ {
+ onError(error) {
+ return 'a digest';
+ },
+ },
+ );
+ rejectText('hello');
+ pipe(writable);
+ });
+ expect(getVisibleChildren(container)).toEqual(loading...
);
+
+ ReactDOMClient.hydrateRoot(
+ container,
+
+ hello
+
,
+ {
+ onRecoverableError(error, errorInfo) {
+ expect(() => {
+ expect(error.digest).toBe('a digest');
+ expect(errorInfo.digest).toBe('a digest');
+ }).toErrorDev(
+ 'Warning: You are accessing "digest" from the errorInfo object passed to onRecoverableError.' +
+ ' This property is deprecated and will be removed in a future version of React.' +
+ ' To access the digest of an Error look for this property on the Error instance itself.',
+ {withoutStack: true},
+ );
+ },
+ },
+ );
+ expect(Scheduler).toFlushWithoutYielding();
+ });
+
describe('error escaping', () => {
it('escapes error hash, message, and component stack values in directly flushed errors (html escaping)', async () => {
window.__outlet = {};
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
index 913a054be2dd2..c18bed4d808d3 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
@@ -2746,6 +2746,7 @@ function updateDehydratedSuspenseComponent(
'client rendering.',
);
}
+ (error: any).digest = digest;
const capturedValue = createCapturedValue(error, digest, stack);
return retrySuspenseComponentWithoutHydrating(
current,
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
index 382e9075716af..7b1f5b9c21b51 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
@@ -2746,6 +2746,7 @@ function updateDehydratedSuspenseComponent(
'client rendering.',
);
}
+ (error: any).digest = digest;
const capturedValue = createCapturedValue(error, digest, stack);
return retrySuspenseComponentWithoutHydrating(
current,
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
index 0e4564538efba..6d244630867b2 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
@@ -2596,9 +2596,11 @@ function commitRootImpl(
const onRecoverableError = root.onRecoverableError;
for (let i = 0; i < recoverableErrors.length; i++) {
const recoverableError = recoverableErrors[i];
- const componentStack = recoverableError.stack;
- const digest = recoverableError.digest;
- onRecoverableError(recoverableError.value, {componentStack, digest});
+ const errorInfo = makeErrorInfo(
+ recoverableError.digest,
+ recoverableError.stack,
+ );
+ onRecoverableError(recoverableError.value, errorInfo);
}
}
@@ -2689,6 +2691,33 @@ function commitRootImpl(
return null;
}
+function makeErrorInfo(digest: ?string, componentStack: ?string) {
+ if (__DEV__) {
+ const errorInfo = {
+ componentStack,
+ digest,
+ };
+ Object.defineProperty(errorInfo, 'digest', {
+ configurable: false,
+ enumerable: true,
+ get() {
+ console.error(
+ 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' +
+ ' This property is deprecated and will be removed in a future version of React.' +
+ ' To access the digest of an Error look for this property on the Error instance itself.',
+ );
+ return digest;
+ },
+ });
+ return errorInfo;
+ } else {
+ return {
+ digest,
+ componentStack,
+ };
+ }
+}
+
function releaseRootPooledCache(root: FiberRoot, remainingLanes: Lanes) {
if (enableCache) {
const pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes);
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
index 496d3f91d5724..36799208dc69b 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
@@ -2596,9 +2596,11 @@ function commitRootImpl(
const onRecoverableError = root.onRecoverableError;
for (let i = 0; i < recoverableErrors.length; i++) {
const recoverableError = recoverableErrors[i];
- const componentStack = recoverableError.stack;
- const digest = recoverableError.digest;
- onRecoverableError(recoverableError.value, {componentStack, digest});
+ const errorInfo = makeErrorInfo(
+ recoverableError.digest,
+ recoverableError.stack,
+ );
+ onRecoverableError(recoverableError.value, errorInfo);
}
}
@@ -2689,6 +2691,33 @@ function commitRootImpl(
return null;
}
+function makeErrorInfo(digest: ?string, componentStack: ?string) {
+ if (__DEV__) {
+ const errorInfo = {
+ componentStack,
+ digest,
+ };
+ Object.defineProperty(errorInfo, 'digest', {
+ configurable: false,
+ enumerable: true,
+ get() {
+ console.error(
+ 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' +
+ ' This property is deprecated and will be removed in a future version of React.' +
+ ' To access the digest of an Error look for this property on the Error instance itself.',
+ );
+ return digest;
+ },
+ });
+ return errorInfo;
+ } else {
+ return {
+ digest,
+ componentStack,
+ };
+ }
+}
+
function releaseRootPooledCache(root: FiberRoot, remainingLanes: Lanes) {
if (enableCache) {
const pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes);