The Magic of useCallback โœจ

Joodi - Jan 14 - - Dev Community

Hey there, devs! ๐Ÿ‘‹

Today, I stumbled upon something that absolutely blew my mind: useCallback. It's a game-changer in React, and I canโ€™t wait to share how it saved me from a frustrating issue and made my code so much better. Let me walk you through my little adventure! ๐Ÿš€

Image description


The Problem ๐Ÿง

I had this function for handling submenu clicks:

const handleSubmenuClick = (submenuName: string) => {
  switch (submenuName) {
    case "add_user":
      router.push("/manage/users/add");
      break;
    case "update_user":
      if (!user_id) {
        alert("Please Select One Atleast!");
      }
      if (user_id) {
        router.push(`/manage/users/edit/${user_id}`);
      }
      break;
    default:
  }
};
Enter fullscreen mode Exit fullscreen mode

Seems fine, right? But here's the catch: every time the component re-rendered, this function would be re-created. That meant unnecessary re-renders and even some weird UI behavior, like the page feeling like it was refreshing. ๐Ÿ˜ฉ Not what I wanted!


Enter useCallback ๐Ÿช„

I needed a way to prevent this function from being recreated unless its dependencies (like user_id or router) actually changed. That's where the useCallback hook came to the rescue! ๐Ÿฆธโ€โ™€๏ธ

Hereโ€™s how I rewrote the function:

const handleSubmenuClick = useCallback(
  (submenuName: string) => {
    const routes: { [key: string]: string } = {
      add_user: "/manage/users/add",
      update_user: user_id ? `/manage/users/edit/${user_id}` : "",
    };

    if (submenuName === "update_user" && !user_id) {
        alert("Please Select One Atleast!");
      return;
    }

    const route = routes[submenuName];
    if (route) {
      router.push(route);
    }
  },
  [router, user_id] // Dependencies
);
Enter fullscreen mode Exit fullscreen mode

Why Is This So Cool? ๐Ÿ˜

  1. No more unnecessary re-creations!

    With useCallback, React remembers the function so it doesn't rebuild it unless the router or user_id changes. ๐Ÿ’พ

  2. Better performance.

    No wasted re-renders or resource usage. ๐ŸŽ๏ธ

  3. Cleaner code.

    By using an object (routes) and useCallback, the logic became easier to follow and extend. ๐Ÿ› ๏ธ


The Result ๐Ÿฅณ

Now, my routing works smoothly, and thereโ€™s no page "refresh" feeling. It's just like using the <Image> component in Next.js: fast, snappy, and delightful. โšก๏ธ

Here's a simplified version of the final function:

const handleSubmenuClick = useCallback(
  (submenuName: string) => {
    const routes = {
      add_user: "/manage/users/add",
      update_user: user_id ? `/manage/users/edit/${user_id}` : "",
    };

    if (submenuName === "update_user" && !user_id) {
      alert("Please select a user first!");
      return;
    }

    const route = routes[submenuName];
    route && router.push(route);
  },
  [router, user_id]
);
Enter fullscreen mode Exit fullscreen mode

Final Thoughts ๐Ÿ’ก

useCallback is one of those hooks that feels like magic once you get it. It helps optimize performance, keeps your app running smoothly, and makes your code look much cleaner. ๐Ÿš€

If youโ€™re not already using it, I highly recommend giving it a try. Itโ€™s the kind of thing that makes you go, โ€œWow, React is amazing!โ€ ๐Ÿ’–

Happy coding! ๐Ÿ–ฅ๏ธโœจ

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .