Skip to content

Commit fb572af

Browse files
jaredpalmergaearon
authored andcommitted
Add more info to invalid hook call error message (#15139)
* Add more info to invalid hook call error message * Update other renderers + change call to action * Update related tests for new hooks error message * Fix lint errors
1 parent a0a2e84 commit fb572af

10 files changed

+96
-20
lines changed

packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,12 @@ describe('ReactHooksInspection', () => {
239239
expect(() => {
240240
ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef);
241241
}).toThrow(
242-
'Hooks can only be called inside the body of a function component.',
242+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
243+
' one of the following reasons:\n' +
244+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
245+
'2. You might be breaking the Rules of Hooks\n' +
246+
'3. You might have more than one copy of React in the same app\n' +
247+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
243248
);
244249

245250
expect(getterCalls).toBe(1);

packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,12 @@ describe('ReactHooksInspectionIntegration', () => {
419419
expect(() => {
420420
ReactDebugTools.inspectHooksOfFiber(childFiber, FakeDispatcherRef);
421421
}).toThrow(
422-
'Hooks can only be called inside the body of a function component.',
422+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
423+
' one of the following reasons:\n' +
424+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
425+
'2. You might be breaking the Rules of Hooks\n' +
426+
'3. You might have more than one copy of React in the same app\n' +
427+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
423428
);
424429

425430
expect(getterCalls).toBe(1);

packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,12 @@ describe('ReactDOMServerHooks', () => {
144144

145145
return render(<Counter />);
146146
},
147-
'Hooks can only be called inside the body of a function component.',
147+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
148+
' one of the following reasons:\n' +
149+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
150+
'2. You might be breaking the Rules of Hooks\n' +
151+
'3. You might have more than one copy of React in the same app\n' +
152+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
148153
);
149154

150155
itRenders('multiple times when an updater is called', async render => {
@@ -626,7 +631,12 @@ describe('ReactDOMServerHooks', () => {
626631

627632
return render(<Counter />);
628633
},
629-
'Hooks can only be called inside the body of a function component.',
634+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
635+
' one of the following reasons:\n' +
636+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
637+
'2. You might be breaking the Rules of Hooks\n' +
638+
'3. You might have more than one copy of React in the same app\n' +
639+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
630640
);
631641
});
632642

packages/react-dom/src/server/ReactPartialRendererHooks.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ let currentHookNameInDev: ?string;
5757
function resolveCurrentlyRenderingComponent(): Object {
5858
invariant(
5959
currentlyRenderingComponent !== null,
60-
'Hooks can only be called inside the body of a function component. ' +
61-
'(https://fb.me/react-invalid-hook-call)',
60+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
61+
' one of the following reasons:\n' +
62+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
63+
'2. You might be breaking the Rules of Hooks\n' +
64+
'3. You might have more than one copy of React in the same app\n' +
65+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
6266
);
6367
if (__DEV__) {
6468
warning(

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,12 @@ function warnOnHookMismatchInDev(currentHookName: HookType) {
262262
function throwInvalidHookError() {
263263
invariant(
264264
false,
265-
'Hooks can only be called inside the body of a function component. ' +
266-
'(https://fb.me/react-invalid-hook-call)',
265+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
266+
' one of the following reasons:\n' +
267+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
268+
'2. You might be breaking the Rules of Hooks\n' +
269+
'3. You might have more than one copy of React in the same app\n' +
270+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
267271
);
268272
}
269273

packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ describe('ReactHooks', () => {
4444
expect(() => {
4545
ReactTestRenderer.create(<Example />);
4646
}).toThrow(
47-
'Hooks can only be called inside the body of a function component.',
47+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen' +
48+
' for one of the following reasons:\n' +
49+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
50+
'2. You might be breaking the Rules of Hooks\n' +
51+
'3. You might have more than one copy of React in the same app\n' +
52+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
4853
);
4954
});
5055
}
@@ -805,15 +810,30 @@ describe('ReactHooks', () => {
805810
const root = ReactTestRenderer.create(<MemoApp />);
806811
// trying to render again should trigger comparison and throw
807812
expect(() => root.update(<MemoApp />)).toThrow(
808-
'Hooks can only be called inside the body of a function component',
813+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
814+
' one of the following reasons:\n' +
815+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
816+
'2. You might be breaking the Rules of Hooks\n' +
817+
'3. You might have more than one copy of React in the same app\n' +
818+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
809819
);
810820
// the next round, it does a fresh mount, so should render
811821
expect(() => root.update(<MemoApp />)).not.toThrow(
812-
'Hooks can only be called inside the body of a function component',
822+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
823+
' one of the following reasons:\n' +
824+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
825+
'2. You might be breaking the Rules of Hooks\n' +
826+
'3. You might have more than one copy of React in the same app\n' +
827+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
813828
);
814829
// and then again, fail
815830
expect(() => root.update(<MemoApp />)).toThrow(
816-
'Hooks can only be called inside the body of a function component',
831+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
832+
' one of the following reasons:\n' +
833+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
834+
'2. You might be breaking the Rules of Hooks\n' +
835+
'3. You might have more than one copy of React in the same app\n' +
836+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
817837
);
818838
});
819839

packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ describe('ReactHooksWithNoopRenderer', () => {
108108
ReactNoop.render(<BadCounter />);
109109

110110
expect(() => ReactNoop.flush()).toThrow(
111-
'Hooks can only be called inside the body of a function component.',
111+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
112+
' one of the following reasons:\n' +
113+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
114+
'2. You might be breaking the Rules of Hooks\n' +
115+
'3. You might have more than one copy of React in the same app\n' +
116+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
112117
);
113118

114119
// Confirm that a subsequent hook works properly.
@@ -131,7 +136,12 @@ describe('ReactHooksWithNoopRenderer', () => {
131136
}
132137
ReactNoop.render(<Counter />);
133138
expect(() => ReactNoop.flush()).toThrow(
134-
'Hooks can only be called inside the body of a function component.',
139+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
140+
' one of the following reasons:\n' +
141+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
142+
'2. You might be breaking the Rules of Hooks\n' +
143+
'3. You might have more than one copy of React in the same app\n' +
144+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
135145
);
136146

137147
// Confirm that a subsequent hook works properly.
@@ -145,7 +155,12 @@ describe('ReactHooksWithNoopRenderer', () => {
145155

146156
it('throws when called outside the render phase', () => {
147157
expect(() => useState(0)).toThrow(
148-
'Hooks can only be called inside the body of a function component.',
158+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
159+
' one of the following reasons:\n' +
160+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
161+
'2. You might be breaking the Rules of Hooks\n' +
162+
'3. You might have more than one copy of React in the same app\n' +
163+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
149164
);
150165
});
151166

packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,12 @@ describe('ReactNewContext', () => {
15141514
}
15151515
ReactNoop.render(<Foo />);
15161516
expect(ReactNoop.flush).toThrow(
1517-
'Hooks can only be called inside the body of a function component.',
1517+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen' +
1518+
' for one of the following reasons:\n' +
1519+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
1520+
'2. You might be breaking the Rules of Hooks\n' +
1521+
'3. You might have more than one copy of React in the same app\n' +
1522+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
15181523
);
15191524
});
15201525

packages/react-test-renderer/src/ReactShallowRenderer.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,12 @@ class ReactShallowRenderer {
218218
_validateCurrentlyRenderingComponent() {
219219
invariant(
220220
this._rendering && !this._instance,
221-
'Hooks can only be called inside the body of a function component. ' +
222-
'(https://fb.me/react-invalid-hook-call)',
221+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
222+
' one of the following reasons:\n' +
223+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
224+
'2. You might be breaking the Rules of Hooks\n' +
225+
'3. You might have more than one copy of React in the same app\n' +
226+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
223227
);
224228
}
225229

packages/react/src/ReactHooks.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ function resolveDispatcher() {
1717
const dispatcher = ReactCurrentDispatcher.current;
1818
invariant(
1919
dispatcher !== null,
20-
'Hooks can only be called inside the body of a function component. ' +
21-
'(https://fb.me/react-invalid-hook-call)',
20+
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
21+
' one of the following reasons:\n' +
22+
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
23+
'2. You might be breaking the Rules of Hooks\n' +
24+
'3. You might have more than one copy of React in the same app\n' +
25+
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
2226
);
2327
return dispatcher;
2428
}

0 commit comments

Comments
 (0)