Learn how custom hooks can help you to write clean code
What are custom hooks?
Hooks were introduced in React 16.8. Hooks are simple functions that allow you to use React state and lifecycle in a functional component. React has some built-in hooks that give and provide the basic functionality to use form and lifecycle.
Custom hooks are user-defined functions prefixed with the “use” keyword. Depending on your logic, custom hooks may call another react hook or custom hook. It may return the function or state that re-renders the react component.
Why should we use custom hooks?
The main reasons to use customs hooks are:
It helps you to separate your logic from the user interface
It allows you to create re-usable logic blocks
It makes your component more understandable
It increases the modularity of your code
When should we use custom hooks?
Below are some cases when you should use custom hooks
- When you are using the same logic in different components
- When your logic is very complex
- When you are working on a large-scale project
How should we use custom hooks?
Before discussing how to use custom hooks, let’s discuss how to write custom hooks.
We will create a basic form that persists the form data on local storage without a custom hook.
export default function App() {
const [firstName, setFirstName] = useState(() => {
if (localStorage.getItem("first-name"))
return localStorage.getItem("first-name") ?? "";
return "";
});
useEffect(() => {
if (firstName) {
localStorage.setItem("first-name", firstName);
}
}, [firstName]);
return (
<div className="App">
<h1>Register Now</h1>
<div className="input-wrapper">
<label>First Name</label>
<input
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
</div>
<button>Submit</button>
</div>
);
}
Now, if you want to add more input fields in the form like Last Name, Email, Phone, Address, and Password, then you have to write the useEffect() hook for each field, and soon your code will get messy and very hard to maintain.
Here custom hook solves this problem by extracting all the logic in the hook itself and returning the states that input fields can use.
Let’s create a custom hook for this logic.
import { useEffect, useState } from "react";
const useLocalStorageState = (key, state) => {
const [localState, setLocalState] = useState(() => {
if (localStorage.getItem(key))
return JSON.parse(localStorage.getItem(key) ?? "");
return state;
});
useEffect(() => {
if (localState) {
localStorage.setItem(key, JSON.stringify(localState));
}
}, [localState]);
return [localState, setLocalState];
};
export default useLocalStorageState;
Important rules for using custom hooks
- Never call Hooks inside loops, conditions, or nested functions.
- Always use Hooks at the top level of your React component.
- Never call Hooks from regular JavaScript functions.
- Instead, call Hooks from React function components or call Hooks from custom Hooks.
Bonus Tip
If you want to follow these rules without checking manually, you can use eslint-plugin-react-hooks, which automatically gives an error on your IDE.
Code sandbox
Try refreshing the code sandbox page after filling out the form.
Conclusion
In this article, we saw how custom hooks could help you separate your logic from the user interface and increase code reusability. We also saw the rules of hooks and how to use the custom hooks. Custom hooks can help you write more clean code and build large-scale projects.
Top comments (2)
Hello Shashwat, Thank you for informative article!
Your code blocks are misaligned and not readable. You can try using
code block
tool. It will look like thisUpdated!
Thank you for suggestion.