Consider this example:
let memoizedCb = React.useCallback(
memoize((param) => () => someFunction(param)),
[]
);
where memoize
is from external library like "fast-memoize". Above code gives warning:
React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead
I found this thread which if we adapt to my use case would suggest this as solution (if I am not wrong):
const memoizedCb = React.useMemo(
() => memoize((param) => () => someFunction(param)),
[]
);
What is the warning about? why does useMemo
fix this problem?
NOTE: someFunction
is defined outside the function component so it is not needed as a dependency.
It seems the warning is there because useCallback
(and also useMemo
see below) expect inline function as argument (don't know why though).
So in the solution from the question:
const memoizedCb = React.useMemo(
() => memoize((param) => () => someFunction(param)),
[]
);
they used useMemo
to imitate useCallback
functionality while also passing an inline function to useMemo
as the warning required:
React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead
That warning is not specific to useCallback
, you get same warning if you just replace useCallback
with useMemo
in the first example:
// For testing
// Gives same warning
let memoizedCb = React.useMemo(
memoize((param) => () => someFunction(param)),
[]
);
As far as I know, the useCallback expects an inline function. If you pass a returned function from another function, eslint won't be able to figure out what are the dependancies of the function, so it will show this warning.
Here I think, eslint is failing to determine the dependancies of somefunction
and thus it cannot evaluate the react-hooks/exhaustive-deps
rule because to evaluate this rule eslint should be able to identify is there any dependancy like state, props for the function passed to useCallback hook. So eslint is asking you to pass an inline function which it will understand and can evalute for lint rules.
As a more general explanation the below will produce a warning:
const someFuncWrap = (fn) => (e) => fn(e)
const memoizedFunc = useCallback(someFuncWrap(foo), [someFuncWrap, foo]);
Changing the useCallback
to a useMemo
with an inline function passes.
const someFuncWrap = (fn) => (e) => fn(e)
const memoizedFunc = useMemo(() => someFuncWrap(foo), [someFuncWrap, foo]);
This is because to parse the hook eslint needs to see it in the following form:
useMemo(() => foo, [foo]);
useCallback((bar) => foo(bar), [foo]);