Using React's useCallback
hook is essentially just a wrapper around useMemo
specialized for functions to avoid constantly creating new function instances within components' props. My question comes from when you need to pass an argued to the callback created from the memoization.
For instance, a callback created like so...
const Button: React.FunctionComponent = props => {
const onClick = React.useCallback(() => alert('Clicked!'), [])
return <button onClick={onClick}>{props.children}</button>
}
is a simple example of a memoized callback and required no external values passed into it in order to accomplish its job. However, if I want to create a generic memoized callback for a React.Dipatch<React.SetStateAction>
function type, then it would require arguments...for example:
const Button: React.FunctionComponent = props => {
const [loading, setLoading] = React.useState(false)
const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), [])
return <button onClick={genericSetLoadingCb(!loading)}>{props.children}</button>
}
In my head, this seems like its the exact same as doing the following...
const Button: React.FunctionComponent = props => {
const [loading, setLoading] = React.useState(false)
return <button onClick={() => setLoading(!loading)}>{props.children}</button>
}
which would let defeat the purpose of memoizing the function because it would still be creating a new function on every render since genericSetLoadingCb(false)
would just be returning a new function on each render as well.
Is this understanding correct, or does the pattern described with arguments still maintain the benefits of memoization?
React.useCallback
on a argument receiving HOF provides no value unless you also memoize the internal function within theuseCallback
usage. – Phalanstery