Extract component logic into reusable functions. If you find yourself copying `useEffect` or `useState` code between components, it's time for a hook.
Imagine having 10 components that all need to know if the user is online. You'd have to copy this effect everywhere.
function UserProfile() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function handleOnline() { setIsOnline(true); }
function handleOffline() { setIsOnline(false); }
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return <div>{isOnline ? 'Online' : 'Offline'}</div>;
}Extract that logic into a function starting with `use`. Now it's reusable!
import { useState, useEffect } from 'react';
export function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
// ... logic to listen to "online"/"offline" events
}, []);
return isOnline;
}function UserProfile() {
const isOnline = useOnlineStatus();
return <div>{isOnline ? 'Active' : 'Away'}</div>;
}
function StatusBar() {
const isOnline = useOnlineStatus();
return <div className={isOnline ? 'green' : 'red'} />;
}You can return anything! Arrays are great if you want the user to rename variables (like useState). Objects are better if there are many values and order shouldn't matter.
function useInput(initial) {
const [val, setVal] = useState(initial);
const onChange = e => setVal(e.target.value);
// Return array: easy to rename!
return [val, onChange];
}
// Consumer:
const [name, setName] = useInput("Alice");
const [email, setEmail] = useInput("");function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
// ... fetch logic ...
// Return object: named properties
return { data, loading };
}
// Consumer:
const { data, loading } = useFetch("/api/user");Custom hooks are just functions that call other hooks. This means they must follow the same rules: