How to Implement useCallback hook with Arguments
Jasser Mark Arioste
Hello, hustler! In this short tutorial, you'll learn how to pass arguments to the function inside a useCallback
hook. We'll also use typescript in this tutorial.
The Problem #
Sometimes, we want to pass a callback function to user events but we want to cache or memoize the function using useCallback
. However, the syntax gets confusing (especially for beginners) when we add a function inside a useCallback
hook. In this tutorial, you'll learn 3 simple steps to implement this and it's not that confusing once you learn it.
Step 1 - Create the Callback function #
First, we just need to create the callback function as normal without using useCallback
. You can already add parameters to your callback function at this point.
For example:
import React from "react"; const MyComponent = () => { const onClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { console.log("button is clicked", e.currentTarget.id); }; return ( <div> <button onClick={onClick} id="my-button"> Click Me! </button> </div> ); }; export default MyComponent;
12345678910111213141516
Notice that we already have the e
parameter for our onClick
handler.
Step 2 - Use the useCallback
hook
#
Next, we just need to pass our callback function to our useCallback
hook. For example:
import React, { useCallback } from "react"; const MyComponent = () => { const onClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { console.log("button is clicked", e.currentTarget.id); }; // pass the onClick handler as-is const memoizedOnClick = useCallback(onClick, []); return ( <div> {/* use the memoizedOnClick handler */} <button onClick={memoizedOnClick} id="my-button"> Click Me! </button> </div> ); }; export default MyComponent;
12345678910111213141516171819
After this step, we have a perfectly memorized event handler. You may stop here depending on your team's coding style.
Step 3 - Refactoring #
The next step is refactoring. Instead of declaring the onClick
handler and passing it to the useCallback
hook, we can directly use the anonymous function instead.
import React, { useCallback } from "react"; const MyComponent = () => { // const onClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { // console.log("button is clicked", e.currentTarget.id); // }; const memoizedOnClick = useCallback((e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { console.log("button is clicked", e.currentTarget.id); }, []); return ( <div> {/* use the memoizedOnClick handler */} <button onClick={memoizedOnClick} id="my-button"> Click Me! </button> </div> ); }; export default MyComponent;
12345678910111213141516171819202122
Checking #
The useCallback
hook ultimately returns the function you pass in it. For example, in your VSCode editor, if you hover over the memoizedOnClick
constant, you'll see that it is a function with the following signature: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) =>void
.
Conclusion #
You learned how to add arguments to the useCallback
hook which ultimately returns whatever function you pass in it in a memoized form which means that it doesn't change between re-renders if its dependencies don't change as well.
Resources #
For further reading, you may check out the React docs.
Credits: Image by Logan Wenger from Pixabay