Custom Hooks
# 05. Custom Hooks
Custom Hooks let you extract component logic into reusable functions.
So far, there have been two popular ways to share stateful logic between components: render props (opens new window) and higher-order components (opens new window). Let's see how Hooks solve the same problems without forcing you to add more components to the tree.
# Extracting a Custom Hook
A custom Hook is a JavaScript function whose name starts with "use" and that may call other Hooks. For example, useFriendStatus below is our first custom Hook:
import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Unlike a React component, a custom Hook doesn't need to have a specific signature. We can decide what it takes as arguments, and what, if anything, it should return. In other words, it's just like a normal function. Its name should always start with use so that you can tell at a glance that the rules of Hooks (opens new window) apply to it.
# Using a Custom Hook
Now that we've extracted this logic to a useFriendStatus hook, we can use it:
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
2
3
4
5
6
7
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
2
3
4
5
6
7
8
9
Is this code equivalent to the original examples? Yes, it works in exactly the same way. If you look closely, you'll notice we didn't make any changes to the behavior. All we did was to extract some common code between two functions into a separate function. Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.
Do I have to name my custom Hooks starting with "use"? Please do. This convention is very important. Without it, we wouldn't be able to automatically check for violations of rules of Hooks (opens new window) because we couldn't tell if a certain function contains calls to Hooks inside of it.
Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.
How does a custom Hook get isolated state? Each call to a Hook gets isolated state. Because we call useFriendStatus directly, from React's point of view our component just calls useState and useEffect. And as we learned (opens new window) earlier (opens new window), we can call useState and useEffect many times in one component, and they will be completely independent.
#
# Summary
- A custom Hook is just like a regular function that contains reusable component logic.
- The function name starts with
use. - State is isolated.