Skip to content

Commit

Permalink
Add errorInfo and prevState parameters to getDerivedStateFromError
Browse files Browse the repository at this point in the history
  • Loading branch information
bisubus committed Jan 15, 2020
1 parent bc1f3e1 commit 622ca61
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
14 changes: 10 additions & 4 deletions packages/react-reconciler/src/ReactFiberThrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,21 @@ function createClassErrorUpdate(
): Update<mixed> {
const update = createUpdate(expirationTime, null);
update.tag = CaptureUpdate;
const inst = fiber.stateNode;
const getDerivedStateFromError = fiber.type.getDerivedStateFromError;
if (typeof getDerivedStateFromError === 'function') {
const error = errorInfo.value;
const stack = errorInfo.stack;
const errorPartialInfo = {
componentStack: stack !== null ? stack : '',
};
const state = inst !== null ? inst.state : null;
update.payload = () => {
logError(fiber, errorInfo);
return getDerivedStateFromError(error);
return getDerivedStateFromError(error, errorPartialInfo, state);
};
}

const inst = fiber.stateNode;
if (inst !== null && typeof inst.componentDidCatch === 'function') {
update.callback = function callback() {
if (__DEV__) {
Expand All @@ -115,9 +120,10 @@ function createClassErrorUpdate(
}
const error = errorInfo.value;
const stack = errorInfo.stack;
this.componentDidCatch(error, {
const errorPartialInfo = {
componentStack: stack !== null ? stack : '',
});
};
this.componentDidCatch(error, errorPartialInfo);
if (__DEV__) {
if (typeof getDerivedStateFromError !== 'function') {
// If componentDidCatch is the only error boundary method defined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1600,16 +1600,23 @@ describe('ReactIncrementalErrorHandling', () => {
]);
});

it('does not provide component stack to the error boundary with getDerivedStateFromError', () => {
it('provides component stack and state to the error boundary with getDerivedStateFromError', () => {
class ErrorBoundary extends React.Component {
state = {error: null};
static getDerivedStateFromError(error, errorInfo) {
expect(errorInfo).toBeUndefined();
return {error};
state = {error: null, foo: 'foo'};
static getDerivedStateFromError(error, errorInfo, prevState) {
expect(error.message).toBe('Hello');
expect(prevState.foo).toBe('foo');
return {error, errorInfo, foo: prevState.foo.toUpperCase()};
}
render() {
if (this.state.error) {
return <span prop={`Caught an error: ${this.state.error.message}`} />;
if (this.state.errorInfo) {
return (
<span
prop={`Caught an error:${normalizeCodeLocInfo(
this.state.errorInfo.componentStack,
)}. Derived foo: ${this.state.foo}.`}
/>
);
}
return this.props.children;
}
Expand All @@ -1625,7 +1632,18 @@ describe('ReactIncrementalErrorHandling', () => {
</ErrorBoundary>,
);
expect(Scheduler).toFlushWithoutYielding();
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]);
expect(ReactNoop.getChildren()).toEqual([
span(
'Caught an error:\n' +
(__DEV__
? ' in BrokenRender (at **)\n'
: ' in BrokenRender\n') +
(__DEV__
? ' in ErrorBoundary (at **).'
: ' in ErrorBoundary.') +
' Derived foo: FOO.',
),
]);
});

it('handles error thrown inside getDerivedStateFromProps of a module-style context provider', () => {
Expand Down

0 comments on commit 622ca61

Please sign in to comment.