UseCallback allows having the same reference for a call back function which has the benefit of only changing when something changes. This is primordial when callbacks are passed down the React component chain to avoid component to be rendered without an actual real reason causing performance issue. The following snippet of code shows a simple button that when clicked invokes an action that set the name to “test”. You can imagine that in a real scenario that the string would come from a real source instead of being hardcoded.
<button onClick={() => { dispatch(AppActions.setName("test")); }} >
The action can often be handled without passing data, or by passing a React’s property and hence can access it from the handler of the action. However, in some cases, where the value is not accessible directly from the outer scope of the handler function, it means that we need to pass by parameter the value. I am reusing a Code Sandbox slightly modified to have the
const setName = useCallback(() => { dispatch(AppActions.setName("test")); }, []);
A quick change with React Hooks to produce the desired scenario is to use useCallback at the top of the component and access it directly in the onClick function callback.
<button onClick={setName}>Change name</button>
At the moment, it works. However, we are not passing any information. Let’s imagine that we cannot access the data directly from the useCallback, how can we still invoke this one?
const setName = useCallback((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { dispatch(AppActions.setName("test")); }, []);
The idea is to have a callback that return a function that as on its turn the input event.
<button onClick={setName("Testing Name")}>Change name</button>
The invocation code change by passing the data. In that example, it is a string, but you can imagine that you are passing the index of the map function or data coming from a source inaccessible from the callback function.
const setName = useCallback( (name: string) => ( event: React.MouseEvent<HTMLButtonElement, MouseEvent> ) => { dispatch(AppActions.setName(name)); }, [] );
My rule of thumb is that I do not need to have this convoluted definition if I am accessing directly properties of the component. Otherwise, I am passing the data needed. I always define the type, which gives me a good quick view about what is passed (
Thx