Skip to content

Commit

Permalink
Remove custom error message from hook access error (#20604)
Browse files Browse the repository at this point in the history
It will still result in a null access error, so there's no change in
semantics. We will print a user-friendly error message in DEV.
  • Loading branch information
acdlite committed Jan 19, 2021
1 parent 9043626 commit 58e8304
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,17 @@ describe('ReactHooksInspection', () => {
};

expect(() => {
ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef);
}).toThrow(
expect(() => {
ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef);
}).toThrow("Cannot read property 'useState' of null");
}).toErrorDev(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',
{withoutStack: true},
);

expect(getterCalls).toBe(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,18 @@ describe('ReactHooksWithNoopRenderer', () => {
}

it('throws when called outside the render phase', () => {
expect(() => useState(0)).toThrow(
expect(() => {
expect(() => useState(0)).toThrow(
"Cannot read property 'useState' of null",
);
}).toErrorDev(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',
{withoutStack: true},
);
});

Expand Down
29 changes: 17 additions & 12 deletions packages/react/src/ReactHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* @flow
*/

import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';
import type {
MutableSource,
MutableSourceGetSnapshotFn,
Expand All @@ -15,25 +16,29 @@ import type {
} from 'shared/ReactTypes';
import type {OpaqueIDType} from 'react-reconciler/src/ReactFiberHostConfig';

import invariant from 'shared/invariant';

import ReactCurrentDispatcher from './ReactCurrentDispatcher';

type BasicStateAction<S> = (S => S) | S;
type Dispatch<A> = A => void;

function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
invariant(
dispatcher !== null,
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',
);
return dispatcher;
if (__DEV__) {
if (dispatcher === null) {
console.error(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',
);
}
}
// Will result in a null access error if accessed outside render phase. We
// intentionally don't throw our own error because this is in a hot path.
// Also helps ensure this is inlined.
return ((dispatcher: any): Dispatcher);
}

export function getCacheForType<T>(resourceType: () => T): T {
Expand Down

0 comments on commit 58e8304

Please sign in to comment.