ReviseAlgo Logo

Hooks

Custom Hooks

Master React Custom Hooks, covering logic extraction, naming conventions, custom fetch and storage implementations, and state sharing mechanics.

Last Updated: July 15, 2026 12 min read

1. Learning Objectives

In this lesson, you will learn how to extract and reuse stateful logic across components. By the end of this topic, you will be able to:

  • Extract stateful logic from components into reusable Custom Hooks.
  • Apply correct naming conventions for custom hooks.
  • Build custom hooks for handling storage (useLocalStorage) and event listeners.
  • Understand that custom hooks share *logic*, not state itself, between components.
  • Implement structured return interfaces (arrays or objects) for custom hooks.

2. Overview

Custom Hooks are JavaScript functions whose names start with use and that can call other Hooks. They allow you to extract stateful component logic (like setting up subscriptions, loading data from APIs, or tracking input states) into reusable functions, keeping your component files clean and focused.

3. Why This Topic Matters

Custom Hooks are the modern standard for writing reusable logic in React:

  • DRY (Don't Repeat Yourself) Code: If multiple components need to perform the same operation (like tracking window dimensions or fetching data), custom hooks allow you to write the logic once and reuse it across components.
  • Cleaner Component Files: Moving complex state declarations, effects, and validation logic into custom hooks keeps your component files small, readable, and focused on rendering the UI.

4. Real-World Analogy

Think of Custom Hooks like **utility power tools in a workshop**:

  • Without Custom Hooks (Manual building): Constructing a drill mechanism from scratch using gears and motors every time you want to build a shelf, desk, or cabinet. This results in duplicated effort and messy workshops.
  • With Custom Hooks (The Power Drill): Buying a standard power drill (the custom hook) once. Whenever you build a cabinet or shelf (different components), you simply plug in the drill. Each project uses the same drill mechanism, but gets its own independent holes. Custom hooks encapsulate the mechanism, providing independent results for each component.

5. Core Concepts

Below is a comparison of HOCs, Render Props, and Custom Hooks:

Feature Higher-Order Components (HOC) Render Props Pattern Custom Hooks (Modern)
Approach Wraps the component in a function that injects props. Passes a rendering function as a child prop. Calls a reusable helper function directly inside the component body.
DOM Nesting Increases nesting, creating wrapper hell. Increases nesting inside templates. No impact on DOM nesting.
Prop conflicts High risk of duplicate prop overrides. None; values are scoped. None; values are explicitly returned.

6. Syntax & API Reference

This example shows a simple custom hook that tracks window size:

7. Visual Diagram

This diagram displays how multiple components consume the same custom hook to get independent, isolated state instances:

8. Live Example — Full Working Code

Below is a complete, single-file HTML page implementing a custom `useLocalStorage` hook:

What just happened? The useLocalStorage hook encapsulates the state declaration, lazy initialization, and local storage synchronization logic. The App component calls the hook just like a built-in Hook, getting back the state value and a setter function. Any updates to name are automatically saved to local storage.

9. Interactive Playground

Try It Yourself Challenges:

  1. Use the useLocalStorage hook inside a second component on the same page, and verify that the two instances manage their state independently.
  2. Modify the hook to return a reset function as a third element in the array to clear the value from local storage.

10. Common Mistakes

Mistake Why it happens Wrong Correct
Omitting the 'use' prefix in the hook name React uses the use prefix to identify custom hooks and enforce the rules of Hooks (like checking if they are called inside conditionals). Omitting the prefix disables these automated checks, which can lead to bugs. function trackWidth() { ... } function useWidth() { ... }
Expecting custom hooks to share state values Custom hooks share *stateful logic*, not the state itself. Every component call to a custom hook creates an independent state instance. Expecting Component A updates to automatically update Component B values when calling the same custom hook. Use React Context or elevate state variables to a common parent component if you need to share state values.

11. Best Practices

  • Always use the `use` prefix: Name your custom hooks starting with `use` (e.g. `useFetch`, `useAuth`) to enable automated linter checks.
  • Keep hooks focused: Each custom hook should do one thing well (like managing a subscription or fetching data). Avoid creating giant, multi-purpose hooks.
  • Return arrays or objects: Return an array (like `useState`) if the consumer should name the returned values, or return an object (like `useFetch`) if there are many returned properties.

12. Browser Compatibility/Requirements

Custom Hooks run consistently across all modern browsers.

13. Interview Questions

Q1: Do custom hooks share state values or stateful logic between components?

Answer: Custom hooks share **stateful logic**, not state itself. Every call to a custom hook creates an independent state instance. If two components call `useLocalStorage('key')`, each component gets its own independent copy of the state, and updating one does not affect the other.

Q2: Why must custom hook names start with the `use` prefix?

Answer: The `use` prefix tells React and linters (like ESLint) that the function is a Custom Hook. This allows the linter to enforce the **Rules of Hooks** (like ensuring Hooks are not called inside conditionals, loops, or nested functions), preventing bugs and ensuring correct execution.

14. Debugging Exercise

Identify the linter error inside this custom hook implementation:

View Solution

Diagnosis: The function calls built-in Hooks (useState, useEffect) but its name does not start with the use prefix. This violates the rules of Hooks, and triggers linter warnings.

Fix: Rename the function starting with use:

15. Practice Exercises

Exercise 1: Create a window connection observer hook

Build a custom hook named useOnlineStatus. Inside it, attach event listeners for window.addEventListener('online') and offline to return a boolean status value dynamically.

16. Scenario-Based Challenge

The Global Theme Listener hook:

You are designing an application that should adapt to the user's operating system dark mode preference (using the CSS media query prefers-color-scheme: dark). Explain how you would write a custom hook named usePrefersDarkMode to listen to matching window query changes and return a boolean value to components.

17. Quick Quiz

Q1: Which naming convention must all Custom Hooks follow?

A) Must start with 'create'

B) Must start with 'use'

C) Must end with 'Hook'

Answer: B — Custom hooks must start with the lowercase prefix 'use' to enable linter validations.

18. Summary & Key Takeaways

  • Custom Hooks allow you to extract and reuse stateful logic between components.
  • Custom hook names must start with the lowercase prefix use.
  • Every component call to a custom hook creates an independent state instance.
  • Return arrays (for flexible naming) or objects (for many returned fields) from custom hooks.

19. Cheat Sheet

Custom Hook Structure Description
function useMyHook() { ... } Defines a custom hook.
return [value, setValue]; Returns an array (allows flexible naming in component destructurings).
return { data, loading, error }; Returns an object (makes it easy to select or ignore specific fields).
---