5 Essential Tips for Custom React Hooks
So how often do you fret that the react 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 };
};
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 stringsuseTimezone
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. 🤮