Let's be real. Have you ever copied and pasted the same chunk of code between two different React components?
Maybe it was code to:
- Fetch data from an API. 
- Manage a form's input values. 
- Listen to keyboard presses. 
- Connect to a websocket. 
If you have, you've felt the pain. It works, but it's messy. And if you find a bug in that code, you have to remember to fix it in every single place you pasted it. Yuck.
What if there was a way to write that logic once and use it everywhere? There is. It's called a Custom Hook.
What is a Custom Hook, Really? (No Jargon)
Imagine you have a favorite power tool, like a drill. You don't build a new drill from scratch every time you need to put up a shelf. You just grab your drill from the toolbox and use it.
A Custom Hook is your personal power tool for React.
It's not a new React feature you have to install. It's just a JavaScript function whose name starts with "use" that can use other hooks inside it.
That's it. You're just making a function.
Let's Build a Tool Together: useLocalStorage
A super common need is to save something to the user's browser (like their username) so it doesn't disappear when they refresh the page.
The Messy Way (Without a Custom Hook):
You'd copy this same useState and useEffect code into every component that needs it
// Inside ComponentOne.js and ComponentTwo.js and... 😩
function MyComponent() {
  const [name, setName] = useState(() => {
    // Get the saved name from the browser when the component starts
    const savedName = localStorage.getItem('name');
    return savedName ? JSON.parse(savedName) : '';
  });
  useEffect(() => {
    // Save the name to the browser every time it changes
    localStorage.setItem('name', JSON.stringify(name));
  }, [name]);
  return <input value={name} onChange={e => setName(e.target.value)} />;
}
The Clean Way (With a Custom Hook):
Let's build our useLocalStorage power tool.
Step 1: Make a new file: useLocalStorage.js
Step 2: Build your tool inside it.
// useLocalStorage.js
import { useState, useEffect } from 'react';
// 1. Our function name starts with 'use'. This makes it a Hook.
function useLocalStorage(key, initialValue) {
  // 2. We can use other Hooks inside our custom Hook! This is the magic.
  const [value, setValue] = useState(() => {
    // Get the saved value from the browser when the hook starts
    const savedValue = localStorage.getItem(key);
    return savedValue ? JSON.parse(savedValue) : initialValue;
  });
  useEffect(() => {
    // Save the value to the browser every time it changes
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  // 3. Return the value and the function to update it, just like useState does!
  return [value, setValue];
}
export default useLocalStorage;
Step 3: Now, use your powerful new tool anywhere!
// Inside AnyComponent.js
import useLocalStorage from './useLocalStorage';
function AnyComponent() {
  // Just ONE line! Look how clean it is! ✨
  const [name, setName] = useLocalStorage('name', '');
  return <input value={name} onChange={e => setName(e.target.value)} />;
}
What Just Happened?
We Wrote Logic Once: All the messy localStorage code is in one place.
1.We Made It Reusable: Any component in our app can now use this useLocalStorage hook.
2.We Made It Easy to Fix: If we find a bug, we fix it in one file (useLocalStorage.js), and it's automatically fixed in every component that uses it.
Your Turn: How to Start
1.Look for repetition. The next time you're about to copy code from one component to another... STOP.
2.Create a new file. Name it use[YourFeature].js (e.g., useApi.js, useToggle.js).
3.Move your repeated code into that function.
4.Return the values that your component needs (usually a value and a setter, just like useState).
Import and use it in your components. Feel like a wizard. 🧙♂️
Custom Hooks aren't about being a React genius. They're about being lazy in the smartest way possible: writing less code and making your life easier.
What's the first thing you'll turn into a custom hook? Share your idea below!
If you’d like to support my content, you can buy me a coffee here:
Buy Me a Coffee
 
 
              
 
    
Top comments (0)