useEffect unable to invoke function directly?
VersionA: useEffect(() => doRequest(), []);
VersionB:
useEffect(() => { doRequest(); }, []);
I’ve always thought both the version are exactly the same, where VersionA is a shortcut and VersionB allowing you to do more than single command within the inline function.
However when I use VersionA, I’m hitting TypeError: func.apply is not a function
, threw by NextJS
If I use syntax of VersionB, everything working fine. Wondering if anyone faced this before?
UPDATES The full code for my component
import { useEffect } from 'react'; import useRequest from '../../hooks/use-request'; import Router from 'next/router'; export default () => { const { doRequest } = useRequest({ url: '/api/users/signout', method: 'post', body: {}, onSuccess: () => Router.push('/'), }); useEffect(() => doRequest(), []); return <div>Signing you out...</div>; };
It’s not exactly the same.
useEffect(() => doRequest(), []);
In this case your callback will implicitly return the value that doRequest()
returns. A useEffect
callback can only return a function (for cleanup of the effect) or undefined
. You can use that syntax if doRequest
either returns nothing (meaning undefined
) or a cleanup function.
EDIT: As noted by @3limin4t0r () => fn()
is the same as () => { return fn(); }
:
useEffect(() => { doRequest(); }, []);
By having a function body and not explicitly returning something your function implicitly returns undefined
which is fine if there is nothing to cleanup.
This is written about in the official docs here.
Any function returned from useEffect
is used for "cleaning up".
In your first example doRequest
returns something other than undefined
, which React will try to call as a function to "clean up" when the component unmounts.
Example of useEffect
with a clean up function:
useEffect(() => { document.addEventListener("resize", handleResize); // This is a "clean up" function return () => { document.removeEventListener("resize", handleResize); }; }, []);
Example of useEffect
without a clean up function. Note this is bad as the listener will still fire after the component unmounts.
useEffect(() => { document.addEventListener("resize", handleResize); }, []);