React useCallback with Parameter React useCallback with Parameter reactjs reactjs

React useCallback with Parameter


For the sake of example below I will use a genericCb function instead of genericSetLoadingCb as you have.

const genericCb = React.useCallback((param) => () => someFunction(param), [])

What we did above is ensure that function genericCb remains the same across rerenders. However, each time you create a new function out of it like this:

genericCb("someParam")

The returned function will be different on each render.To also ensure the returned function is memoized, you need something like this:

 let memoizedCb = React.useCallback(    memoize((param) => () => someFunction(param)),    []  );

I use fast memoize, e.g.

import memoize from "fast-memoize";

Now if you use 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 areunknown. 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 hitmemoized = memoize(fn); // without useCallback this would happen on next render // Now the previous cache is lost


It seems like doing the following is an elegant and simple way to solve your problem. It won't create a new cb function if Button is just rerendering.

const Button = props => {    const [loading, setLoading] = React.useState(false)    const cb = React.useCallback(() => { setLoading(!loading) }, [loading]);    return <button onClick={cb}>{props.children}</button>}