Customs hooks are a powerful part of the new hooks api of React. In this article I will give an example to show off how to build a custom hook and when you might want to do this.
Rules of custom hooks
First, I want to enumerate some rules of hooks. Usually the names of custom hooks begin with use in the name, like useState, useReducer, etc. I think it is best to follow that pattern although I am not positive it must begin with use. The other rules are as follows,
- Hooks can be called from within React function components
- Hooks can be called from within custom hooks
- Hooks can't be called within conditional logic, loops, etc. They must be called in the same order each time.
Reasons for using custom hooks
With the release of hooks, React function components can now have state and lifecycle effects. This allows us to share code and create new abstractions. There are different reasons you might want to create a custom hook.
A good time to turn to custom hooks is when there is duplication between components. When you notice it, you can extract out a custom hook and use it in both places. Perhaps another good time to use a custom hook is when a component has complicated logic and extracting it into a hook with a good name would help make the code cleaner and clearer.
Clock Component
In the example below, I have a basic example of a component that displays the current time. We are going to extract out the state and effect so that we can show the current time in lots of places. Before hooks, you probably would have had to use a higher order class or the render prop pattern. Hooks allows us to share this code without having a lot of nesting divs and components.
A few things I want to review before we extract what we need into our custom hook. When we call useState it takes in the initial state and returns an array of two things that we can name whatever we want. The first is a reference to the state and the second is a function that will update the state. The useEffect hook will run when the component mounts because we provided the empty array. When it unmounts, it will run the function that I return from the function I gave to useEffect which will clear out the interval.
const Clock = () => {
const [clock, setClock] = useState(new Date().toLocaleTimeString());
useEffect(() => {
let id = setInterval(() => {
setClock(new Date().toLocaleTimeString());
}, 1000);
return () => clearInterval(id);
}, []);
return <h1>{clock}</h1>;
}
Below I have extracted setting up the state and the effect. I then return just the state which is clock. Anywhere the useClock is used it will run these hooks and return the clock state.
const useClock = () => {
const [clock, setClock] = useState(new Date().toLocaleTimeString());
useEffect(() => {
let id = setInterval(() => {
setClock(new Date().toLocaleTimeString());
}, 1000);
return () => clearInterval(id);
}, []);
return clock;
}
const Clock = () => {
const clock = useClock();
return <h1>{clock}</h1>;
}
Final Thoughts
Hooks are an excellent way to cleaner React code. They are a powerful new part of the React api. As you begin to use hooks look for custom hooks that you can extract from your function components remove duplication from your codebase.
Top comments (1)
Why create one when you can get all awesome hooks in a single library?
Try scriptkavi/hooks. Copy paste style and easy to integrate with its own CLI