update error message to include useLayoutEffect or useEffect on bad e… (#22279)
* update error message to include useLayoutEffect or useEffect on bad effect return * Update packages/react-reconciler/src/ReactFiberCommitWork.new.js Co-authored-by: Ricky <rickhanlonii@gmail.com> * use existing import Co-authored-by: Ricky <rickhanlonii@gmail.com>
salazarm committed
Sep 10, 2021 at 12:19 UTC
0fd195f2955478636ccab840676c19bb29874b96
3 files changed
+35
-15
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+14
-4
@@ -507,7 +507,7 @@ function commitHookEffectListUnmount(
507
}
508
}
509
510
-function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
510
+function commitHookEffectListMount(tag: HookFlags, finishedWork: Fiber) {
511
const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);
512
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
513
if (lastEffect !== null) {
@@ -522,6 +522,12 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
522
if (__DEV__) {
523
const destroy = effect.destroy;
524
if (destroy !== undefined && typeof destroy !== 'function') {
525
+ let hookName;
526
+ if ((effect.tag & HookLayout) !== NoFlags) {
527
+ hookName = 'useLayoutEffect';
528
+ } else {
529
+ hookName = 'useEffect';
530
+ }
531
let addendum;
532
if (destroy === null) {
533
addendum =
@@ -529,10 +535,13 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
535
'up, return undefined (or nothing).';
536
} else if (typeof destroy.then === 'function') {
537
addendum =
532
- '\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' +
538
+ '\n\nIt looks like you wrote ' +
539
+ hookName +
540
+ '(async () => ...) or returned a Promise. ' +
541
'Instead, write the async function inside your effect ' +
542
'and call it immediately:\n\n' +
535
- 'useEffect(() => {\n' +
543
+ hookName +
544
+ '(() => {\n' +
545
' async function fetchData() {\n' +
546
' // You can await here\n' +
547
' const response = await MyAPI.getData(someId);\n' +
@@ -545,8 +554,9 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
554
addendum = ' You returned: ' + destroy;
555
}
556
console.error(
548
- 'An effect function must not return anything besides a function, ' +
557
+ '%s must not return anything besides a function, ' +
558
'which is used for clean-up.%s',
559
+ hookName,
560
addendum,
561
);
562
}
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+14
-4
@@ -507,7 +507,7 @@ function commitHookEffectListUnmount(
507
}
508
}
509
510
-function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
510
+function commitHookEffectListMount(tag: HookFlags, finishedWork: Fiber) {
511
const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);
512
const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
513
if (lastEffect !== null) {
@@ -522,6 +522,12 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
522
if (__DEV__) {
523
const destroy = effect.destroy;
524
if (destroy !== undefined && typeof destroy !== 'function') {
525
+ let hookName;
526
+ if ((effect.tag & HookLayout) !== NoFlags) {
527
+ hookName = 'useLayoutEffect';
528
+ } else {
529
+ hookName = 'useEffect';
530
+ }
531
let addendum;
532
if (destroy === null) {
533
addendum =
@@ -529,10 +535,13 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
535
'up, return undefined (or nothing).';
536
} else if (typeof destroy.then === 'function') {
537
addendum =
532
- '\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' +
538
+ '\n\nIt looks like you wrote ' +
539
+ hookName +
540
+ '(async () => ...) or returned a Promise. ' +
541
'Instead, write the async function inside your effect ' +
542
'and call it immediately:\n\n' +
535
- 'useEffect(() => {\n' +
543
+ hookName +
544
+ '(() => {\n' +
545
' async function fetchData() {\n' +
546
' // You can await here\n' +
547
' const response = await MyAPI.getData(someId);\n' +
@@ -545,8 +554,9 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
554
addendum = ' You returned: ' + destroy;
555
}
556
console.error(
548
- 'An effect function must not return anything besides a function, ' +
557
+ '%s must not return anything besides a function, ' +
558
'which is used for clean-up.%s',
559
+ hookName,
560
addendum,
561
);
562
}
packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
+7
-7
@@ -2647,7 +2647,7 @@ describe('ReactHooksWithNoopRenderer', () => {
2647
root1.render(<App return={17} />);
2648
}),
2649
).toErrorDev([
2650
- 'Warning: An effect function must not return anything besides a ' +
2650
+ 'Warning: useEffect must not return anything besides a ' +
2651
'function, which is used for clean-up. You returned: 17',
2652
]);
2653
@@ -2657,7 +2657,7 @@ describe('ReactHooksWithNoopRenderer', () => {
2657
root2.render(<App return={null} />);
2658
}),
2659
).toErrorDev([
2660
- 'Warning: An effect function must not return anything besides a ' +
2660
+ 'Warning: useEffect must not return anything besides a ' +
2661
'function, which is used for clean-up. You returned null. If your ' +
2662
'effect does not require clean up, return undefined (or nothing).',
2663
]);
@@ -2668,7 +2668,7 @@ describe('ReactHooksWithNoopRenderer', () => {
2668
root3.render(<App return={Promise.resolve()} />);
2669
}),
2670
).toErrorDev([
2671
- 'Warning: An effect function must not return anything besides a ' +
2671
+ 'Warning: useEffect must not return anything besides a ' +
2672
'function, which is used for clean-up.\n\n' +
2673
'It looks like you wrote useEffect(async () => ...) or returned a Promise.',
2674
]);
@@ -2873,7 +2873,7 @@ describe('ReactHooksWithNoopRenderer', () => {
2873
root1.render(<App return={17} />);
2874
}),
2875
).toErrorDev([
2876
- 'Warning: An effect function must not return anything besides a ' +
2876
+ 'Warning: useLayoutEffect must not return anything besides a ' +
2877
'function, which is used for clean-up. You returned: 17',
2878
]);
2879
@@ -2883,7 +2883,7 @@ describe('ReactHooksWithNoopRenderer', () => {
2883
root2.render(<App return={null} />);
2884
}),
2885
).toErrorDev([
2886
- 'Warning: An effect function must not return anything besides a ' +
2886
+ 'Warning: useLayoutEffect must not return anything besides a ' +
2887
'function, which is used for clean-up. You returned null. If your ' +
2888
'effect does not require clean up, return undefined (or nothing).',
2889
]);
@@ -2894,9 +2894,9 @@ describe('ReactHooksWithNoopRenderer', () => {
2894
root3.render(<App return={Promise.resolve()} />);
2895
}),
2896
).toErrorDev([
2897
- 'Warning: An effect function must not return anything besides a ' +
2897
+ 'Warning: useLayoutEffect must not return anything besides a ' +
2898
'function, which is used for clean-up.\n\n' +
2899
- 'It looks like you wrote useEffect(async () => ...) or returned a Promise.',
2899
+ 'It looks like you wrote useLayoutEffect(async () => ...) or returned a Promise.',
2900
]);
2901
2902
// Error on unmount because React assumes the value is a function