DEV Community

Elham Najeebullah
Elham Najeebullah

Posted on

React & TypeScript: useCallback Hook

What is useCallback Hook?
useCallback is a React Hook that allows you to memoize a function. It takes a function and an array of dependencies as arguments, and returns a memoized version of the function.

Why use it?
The main purpose of useCallback is to improve the performance of your React application by preventing unnecessary re-renders. When a component re-renders, all of its child components also re-render, even if their props haven't changed. If a child component receives a callback function as a prop, it will cause the child component to re-render every time the parent component re-renders, even if the callback function is the same.

By using useCallback, you can ensure that the callback function is only recreated if one of its dependencies has changed. This can significantly improve the performance of your application, especially when you have a large number of child components or when the child components are expensive to render.

Here's an example of how to use useCallback:

import { useCallback } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]); // only re-create the handleClick function if count changes

  return (
    <ChildComponent onClick={handleClick} />
  );
}

function ChildComponent({ onClick }: { onClick: () => void }) {
  return <button onClick={onClick}>Click me</button>;
}

Enter fullscreen mode Exit fullscreen mode

In this example, the handleClick function is only recreated if the count state changes, which means that the ChildComponent will not re-render unless the count state changes.

It's important to note that you should only pass the minimal set of values as dependencies to useCallback otherwise it will re-create the function on every re-render which will make the performance worse.

How to use useEffect hook with useCallback?
The useEffect hook can be used with the useCallback hook to improve the performance of your application. Here is an example of how to use useEffect with useCallback:

import { useEffect, useState, useCallback } from 'react';

function MyComponent() {
  const [data, setData] = useState<MyDataType | null>(null);

  const fetchData = useCallback(() => {
    // fetch data and update state
  }, []);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  return <div>{data}</div>;
}

Enter fullscreen mode Exit fullscreen mode

In this example, useCallback is used to create a fetchData function that is only recreated if its dependencies change. The useEffect hook is then used to invoke the fetchData function when the component is mounted and when the fetchData function changes.

By using useCallback to memoize the fetchData function, we ensure that it is only recreated if its dependencies change. This means that the useEffect hook will not invoke the fetchData function unnecessarily, which can improve the performance of your application.

It's important to note that if the dependencies passed to the useCallback hook are not changing, the callback function will stay the same on every re-render and it will not cause unnecessary re-renders.

useEffect + useCallback to handle cleanup logic
You can also use useEffect and useCallback together to handle cleanup logic. Here's an example of how you can use them together to handle cleanup logic:

import { useEffect, useState, useCallback } from 'react';

function MyComponent() {
  const [data, setData] = useState<MyDataType | null>(null);

  const handleData = useCallback((data: MyDataType) => {
    setData(data);
  }, []);

  useEffect(() => {
    const subscription = someDataSource.subscribe(handleData);
    return () => {
      subscription.unsubscribe();
    };
  }, [handleData]);

  return <div>{data}</div>;
}

Enter fullscreen mode Exit fullscreen mode

In this example, we are using useCallback to create a handleData function that is only recreated if its dependencies change. The useEffect hook is then used to subscribe to a data source and pass the handleData function as a callback. The useEffect hook also returns a cleanup function that is invoked when the component is unmounted or when the handleData function changes, in which case it unsubscribes from the data source.

Note that in this case, handleData is used as a dependency for the useEffect hook, this way the subscription is only created when the handleData callback change. This ensures that the component will not subscribe to the data source multiple times and will not cause unnecessary re-renders.

Top comments (0)