diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index b38b888fd4029..bde9173a28f69 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -507,7 +507,7 @@ function commitHookEffectListUnmount( } } -function commitHookEffectListMount(tag: number, finishedWork: Fiber) { +function commitHookEffectListMount(tag: HookFlags, finishedWork: Fiber) { const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any); const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; if (lastEffect !== null) { @@ -522,6 +522,12 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { if (__DEV__) { const destroy = effect.destroy; if (destroy !== undefined && typeof destroy !== 'function') { + let hookName; + if ((effect.tag & HookLayout) !== NoFlags) { + hookName = 'useLayoutEffect'; + } else { + hookName = 'useEffect'; + } let addendum; if (destroy === null) { addendum = @@ -529,10 +535,13 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { 'up, return undefined (or nothing).'; } else if (typeof destroy.then === 'function') { addendum = - '\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' + + '\n\nIt looks like you wrote ' + + hookName + + '(async () => ...) or returned a Promise. ' + 'Instead, write the async function inside your effect ' + 'and call it immediately:\n\n' + - 'useEffect(() => {\n' + + hookName + + '(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + @@ -545,8 +554,9 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { addendum = ' You returned: ' + destroy; } console.error( - 'An effect function must not return anything besides a function, ' + + '%s must not return anything besides a function, ' + 'which is used for clean-up.%s', + hookName, addendum, ); } diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index 2bae266c60dc2..241bc5a5dbae3 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -507,7 +507,7 @@ function commitHookEffectListUnmount( } } -function commitHookEffectListMount(tag: number, finishedWork: Fiber) { +function commitHookEffectListMount(tag: HookFlags, finishedWork: Fiber) { const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any); const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; if (lastEffect !== null) { @@ -522,6 +522,12 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { if (__DEV__) { const destroy = effect.destroy; if (destroy !== undefined && typeof destroy !== 'function') { + let hookName; + if ((effect.tag & HookLayout) !== NoFlags) { + hookName = 'useLayoutEffect'; + } else { + hookName = 'useEffect'; + } let addendum; if (destroy === null) { addendum = @@ -529,10 +535,13 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { 'up, return undefined (or nothing).'; } else if (typeof destroy.then === 'function') { addendum = - '\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' + + '\n\nIt looks like you wrote ' + + hookName + + '(async () => ...) or returned a Promise. ' + 'Instead, write the async function inside your effect ' + 'and call it immediately:\n\n' + - 'useEffect(() => {\n' + + hookName + + '(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + @@ -545,8 +554,9 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) { addendum = ' You returned: ' + destroy; } console.error( - 'An effect function must not return anything besides a function, ' + + '%s must not return anything besides a function, ' + 'which is used for clean-up.%s', + hookName, addendum, ); } diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index 342c8abf9a254..9069ca71c71e4 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -2647,7 +2647,7 @@ describe('ReactHooksWithNoopRenderer', () => { root1.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useEffect must not return anything besides a ' + 'function, which is used for clean-up. You returned: 17', ]); @@ -2657,7 +2657,7 @@ describe('ReactHooksWithNoopRenderer', () => { root2.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useEffect must not return anything besides a ' + 'function, which is used for clean-up. You returned null. If your ' + 'effect does not require clean up, return undefined (or nothing).', ]); @@ -2668,7 +2668,7 @@ describe('ReactHooksWithNoopRenderer', () => { root3.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useEffect must not return anything besides a ' + 'function, which is used for clean-up.\n\n' + 'It looks like you wrote useEffect(async () => ...) or returned a Promise.', ]); @@ -2873,7 +2873,7 @@ describe('ReactHooksWithNoopRenderer', () => { root1.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useLayoutEffect must not return anything besides a ' + 'function, which is used for clean-up. You returned: 17', ]); @@ -2883,7 +2883,7 @@ describe('ReactHooksWithNoopRenderer', () => { root2.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useLayoutEffect must not return anything besides a ' + 'function, which is used for clean-up. You returned null. If your ' + 'effect does not require clean up, return undefined (or nothing).', ]); @@ -2894,9 +2894,9 @@ describe('ReactHooksWithNoopRenderer', () => { root3.render(); }), ).toErrorDev([ - 'Warning: An effect function must not return anything besides a ' + + 'Warning: useLayoutEffect must not return anything besides a ' + 'function, which is used for clean-up.\n\n' + - 'It looks like you wrote useEffect(async () => ...) or returned a Promise.', + 'It looks like you wrote useLayoutEffect(async () => ...) or returned a Promise.', ]); // Error on unmount because React assumes the value is a function