5 Essential Tips for Custom React Hooks

Dayvster 馃寠 - Sep 29 '22 - - Dev Community

So how often do you fret that the hook you are currently writing is never going to be re-used in your entire application except in one single lonely instance, or how about what should that hook even handle, what goes in that hook should you write a hook that depends on another hook or should both of those just be one mega hook that return an easy to destructure object that allows you or your team mates to access the hooks state or methods. Oh and then there's all those super useful hook libraries that are just one wbe search away where your ideal hook is just a quick copy paste away, should you use those or should you write your own? Well, I'm here to tell you that you should write your own, and I'm going to give you 5 tips to help you write better custom hooks.

1. Reusability is king 馃憫

The first thing you should ask yourself when writing a custom hook is "Will this hook be re-used in multiple places in my application?", or even does it have the potential to be re-used in multiple places. The answer is not as easy as you might think. Let's for example say that we have a custom hook named useAuth which handles your authentication logic such as logging the user in logging the user out, retrieving some information about the user and storing it somewhere easily accesible even if the user closes their browser etc. Your first thought might be well the user only ever needs to log in and log out once and the user info can just be stored in the application state, so clearly this is not an ideal candidate for a hook.

However do you really want to vendor lock your auth to whatever application state library you're currently using. Do you really want to have to rewrite your auth logic over and over and over again for every single application you write? How about if the maintainer of that library decides to no longer maintain their codebase or even worse changes a core part of their codebase that breaks your auth logic. Do you really wanna trust someone else with your applications security? No, you don't.

Which is why a useAuth hook is an ideal candidate for a custom hook. But you may be wondering okay but the login and logout will still only ever be used once by the user so what's the point if it's not reusable. Now sure that part may not be all that reusable, however the part that retrieves the user info and stores it somewhere easily accessible is reusable. So you can have a useAuth hook that handles the login and logout and a useUser hook that handles the retrieval of the user info and storing it somewhere easily accessible. Furthermore you can call the useUser hook inside of the useAuth hook so that you can easily access the user info in the useAuth hook by simply returning the user info from the useAuth hook

Example:

// useAuth.ts
import { useUser } from "./useUser"; // import the useUser hook

export const useAuth = () => {
  const { user, setUser, clearUser } = useUser(); 

  const login = async (email: string, password: string) => {
    // login logic goes here i.e via react-query or axios
    setUser(user);
  };

  const logout = async () => {
    // logout logic goes here i.e via react-query or axios
    clearUser(); // if you're storing your user info in local storage this method should delete it
  };

  // return the user and the login and logout methods
  return { user, login, logout };
};
Enter fullscreen mode Exit fullscreen mode

2. Don't overcomplicate your hooks

The second mistake I see people make is over engineer their custom hooks into these mega hooks that tackle too much functionallity at once. Optimally you'd want to follow the do one thing and do it well principle here. Meaning if you wanna write a hook that transforms your dates into nice human readable strings then you should not also try and cram in functionality that handles timezone logic or any of that stuff. You'd optimally have:

  • useRelativeDates hook that handles transforming dates into human readable strings
  • useTimezone hook that handles timezone logic, whatever it may be

Remember simplicity is key, but don't overdo it please. No need to have hooks that are 5 lines long and do nothing but return a value. Unless you have a very specific use case for that.

Everything in moderation grasshopper.

3. Plan out your hooks

Seriously I know I've gone into this whole thing in my other blog post How Granular Should your Components be

But really, measure twice cut once. It's much easier to plan our a rough idea or concept of what your application and it's individual parts before you write a single line of code. This naturally comes with experience as well so if you're a fairly experienced developer maybe you don't need a planning phase for every single hook or component you write. But I'd consider myself fairly experienced and I can tell you with full certainty whenever I do take my time to plan out and scaffold my code before I write it I end up with much cleaner and maintainable code and I catch a lot of mistakes or weird trains of thought that I would have otherwise missed or would have mindlesly implemented while jamming out to some tunes.

4. Do search up other peoples hooks, don't copy paste

I know it's super tempting to just type in custom hook useWord into your favorite search engine, find the one that matches your use case the closest, copy paste it and be done with it. But that's not the right way to go about it. Firstly you're robbing yourself of a learning experience, secondly you can never be 100% sure the hook you've found is written in a way that suits your use case perfectly and you REALLY do not want to adjust your use case to fit the hook. That would be backwards.

Instead do look up a hook that somebody else has created, read it through, study it and see which parts fit your use case and which do not. Use the parts that do fit and throw away the rest, add some of your own stuff to it and then you've got yourself a custom hook that you can be proud of and is truly your own and should fit your specific use case perfectly.

5. Don't be afraid to write a hook that depends on another hook

We already covered this in our first example, instead of writing a big mega hook that tackles a lot of functionality consider writing multiple smaller hooks that are very specific the word that comes after use should always perfectly describe what the hook does, e.g useAuth, useUser, useLocalStorage, useAxios, useNewsApi etc.

We've already covered that you can use one hook inside of another and then return the values of both hooks in an easily deconstructable object.

There is nothing wrong with taking this approach if anything it ties into the whole philosophy of react and react hooks. React is all about composition and reusability and so are react hooks. So don't be afraid to use one hook inside of another.

Conclusion

I hope this post has helped you understand the importance of custom hooks and how to write them. I've been writing custom hooks for a while now and I can tell you with full certainty that they are one of the most powerful tools in your react developer toolbelt. They essentially allow us to abstract functionality away from our components into reusable functions that we can use in multiple places in our application. All of this without having to resort to any nasty OOP. 馃ぎ

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