React Hooks - useCallback

React Hooks - useCallback

ยท

3 min read

What is useCallback?

The hook allows you to cache a function definition and optimize the performance of your component by only re-rendering if one of its dependencies has changed. This hook works similarly to useMemo, but to memorize function instead.

The hook takes 2 parameters: function, and dependencies.

  • function - the value of the function that you want to cache or remember
  • dependencies - this is to tell the hook to re-run when one of the dependencies' values changed

Imagine you have a toolbox containing a hammer, a screwdriver, and a wrench that are all in brand-new condition. The toolbox represents the useCallback hook, which keeps track of the condition of these tools. Every time you use a tool, its condition slowly degrades, but you don't have to replace the tool right away. For example, you used the hammer many times and it is wearing out faster than the other 2 tools. One day, you replaced the old and worn-out hammer with a brand-new hammer. This is when the toolbox will "re-render" because the hammer dependency is changed. This is similar to how a component will only re-render if one of its dependencies has changed, as determined by the useCallback hook.

Why React re-render?

React re-renders whenever its state or value changes. Remember how JavaScrip evaluates equals for string, number, array, object, and function? As long as, the state or value reminds the same, re-render should not happen, however, that is not the case for arrays, objects, and functions.

See the function example below, both functions return the same value hi, but when you use triple equals and get a false result. The useCallback hook is to remember the value from the function and then both functions will be the "same".

console.log("Number comparsion", 1 === 1); // true
console.log("String comparsion", "hi" === "hi"); // true
console.log("Array comparsion", [] === []); // false
console.log("Object comparsion", {} === {}); // false

function ff1() {
  return "hi";
}

function ff2() {
  return "hi";
}

console.log("Function comparion", ff1 === ff2); // false

The difference between with and without useCallback

Without useCallback

As you can see, I typed hello (5 letters) and the console shows it logged the same thing 5 times. This tells us that the app was re-rendered 5 times.

chrome_juMNXmcUBF

With useCallback

Let's add useCallback hook. I typed hello like I did before and the console doesn't show any logged value. This is because useCallback hook knows the function value is the same as before, therefore, the app did not re-render.

chrome_4MFuH0eUfG

Test Code

I borrowed partial code from Dave Gray's video and I listed it as one of the resources below.

function App() {
  const [userInput, setUserInput] = useState("");
  const [num1] = useState(4);
  const [num2] = useState(5);

  const sum = () => num1 + num2;
  // const sum = useCallback(() => num1 + num2, [num1, num2]);

  useEffect(() => {
    console.log(`New sum value: ${sum()}`);
  }, [sum]);

  return (
    <main className="App">
      <input
        type="text"
        placeholder="input"
        value={userInput}
        onChange={(e) => setUserInput(e.target.value)}
      />
      <h2>Output: {userInput || "--"}</h2>
      <h2>Sum: {sum()}</h2>
    </main>
  );
}

Recap

The useCallback and the useMemo hooks have similar functionality in preventing unnecessary re-renders and improving the performance of React apps. However, it's not necessary to wrap all functions with useCallback and it depends on the app structure and the specific use case. A good practice is to use React DevTools to inspect which components are causing performance issues, and then determine if useCallback or useMemo would be an appropriate solution in those cases.

Resources

Thank you!

Thank you for your time and for reading this!

Originally published at victoriacheng15.vercel.app

Did you find this article valuable?

Support Victoria by becoming a sponsor. Any amount is appreciated!

ย