DEV Community

Cover image for The Magic of useCallback ✨
Joodi
Joodi

Posted on

The Magic of useCallback ✨

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! πŸ–₯️✨

Top comments (0)