For this example I will use a genericCb
function instead of genericSetLoadingCb
as you have:
const genericCb = React.useCallback((param) => () => someFunction(param), [])
Now, what we did above is ensure that function genericCb
remains the same across renders (due to usage of useCallback
).
However, each time you call genericCb
to create a new function out of it like this:
genericCb("someParam")
The returned function will still be different on each render.
To also ensure the returned function is memoized for some input, you should additionally use some memoizing approach:
let memoizedCb = React.useCallback(
memoize((param) => () => someFunction(param)),
[]
);
For example you can use fast-memoize
library, e.g.
import memoize from "fast-memoize";
Now if you call memoizedCb("someParam")
to generate a function, it will return same function on each render, provided "someParam"
also remains the same.
Note: As pointed out in the comments this approach seems to produce warning (it didn't in my project though):
React Hook useCallback received a function whose dependencies are
unknown. Pass an inline function instead
It seems the warning is there because since we passed memoize
to useCallback
, it can't see the dependencies anymore and can't warn you about possible stale closures. In that case IMHO it is up to the user to check if there are any stale closures.
Simply using memoize without useCallback
wouldn't work, as on next render it would invoke memoize from fresh like this:
let memoized = memoize(fn)
memoized('foo', 3, 'bar')
memoized('foo', 3, 'bar') // cache hit
memoized = memoize(fn); // without useCallback this would happen on next render
// Now the previous cache is lost
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…