Building Custom Hooks

0/2 in this phase0/36 across the roadmap

📖 Concept

Custom Hooks are the ultimate way to share logic between components. If you find yourself writing the same useEffect or useState logic in multiple places, it's time to extract it into a custom hook.

What is a Custom Hook? It's just a regular JavaScript function whose name starts with "use" and that can call other hooks.

Benefits:

  1. Reusability: Write logic once, use it everywhere.
  2. Clean Components: Keep your UI components focused on rendering, while the hook handles the "how".
  3. Testability: You can test a custom hook independently of any specific component.
  4. Composability: You can build complex hooks by combining simpler ones.

💻 Code Example

codeTap to expand ⛶
1import { useState, useEffect } from 'react';
2
3// 1. A Custom Hook for LocalStorage
4function useLocalStorage(key, initialValue) {
5 // Get initial value from storage or use provided initialValue
6 const [storedValue, setStoredValue] = useState(() => {
7 try {
8 const item = window.localStorage.getItem(key);
9 return item ? JSON.parse(item) : initialValue;
10 } catch (error) {
11 console.error(error);
12 return initialValue;
13 }
14 });
15
16 // Return a wrapped version of useState's setter function that
17 // persists the new value to localStorage.
18 const setValue = (value) => {
19 try {
20 // Allow value to be a function so we have same API as useState
21 const valueToStore = value instanceof Function ? value(storedValue) : value;
22 setStoredValue(valueToStore);
23 window.localStorage.setItem(key, JSON.stringify(valueToStore));
24 } catch (error) {
25 console.error(error);
26 }
27 };
28
29 return [storedValue, setValue];
30}
31
32// 2. Usage in a component
33function App() {
34 const [name, setName] = useLocalStorage('name', 'Stranger');
35
36 return (
37 <input
38 type="text"
39 value={name}
40 onChange={(e) => setName(e.target.value)}
41 className="border p-2"
42 />
43 );
44}

🏋️ Practice Exercise

  1. Build a useFetch hook that handles data, loading, and error states for any URL.
  2. Create a useWindowSize hook that returns the current width and height of the browser.
  3. Implement a useDebounce hook to delay the update of a value (useful for search inputs).
  4. Build a useOnClickOutside hook that detects when a user clicks outside a specific element (like a modal).

⚠️ Common Mistakes

  • Not starting the function name with 'use' (React's linter won't be able to check for hook rules).

  • Thinking custom hooks share state (they don't; every time you use a hook, it gets its own isolated state).

  • Putting UI/JSX inside a custom hook (hooks should only handle logic and data).

  • Over-abstracting: creating a hook for logic that is only used in one place and is very simple.

💼 Interview Questions

🎤 Mock Interview

Practice a live interview for Building Custom Hooks