Bird
Raised Fist0
Reactframework~5 mins

Creating custom hooks in React

Choose your learning style10 modes available
Introduction

Custom hooks let you reuse logic in React components easily. They keep your code clean and simple.

You want to share stateful logic between multiple components.
You need to organize complex logic into smaller, reusable parts.
You want to keep your components focused on UI, not logic.
You want to avoid repeating the same code in different places.
Syntax
React
function useCustomHookName() {
  // use React hooks like useState, useEffect here
  return someValue;
}

Custom hook names must start with use to follow React rules.

Inside custom hooks, you can use other hooks like useState or useEffect.

Examples
This hook manages a counter state and returns the count and a function to increase it.
React
function useCounter() {
  const [count, setCount] = React.useState(0);
  const increment = () => setCount(count + 1);
  return { count, increment };
}
This hook tracks the window width and updates it when the window resizes.
React
function useWindowWidth() {
  const [width, setWidth] = React.useState(window.innerWidth);
  React.useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return width;
}
Sample Program

This component uses a custom hook useToggle to manage a boolean state. The button toggles the state between ON and OFF. It also includes accessibility with aria-pressed and aria-label.

React
import React from 'react';

function useToggle(initialValue = false) {
  const [value, setValue] = React.useState(initialValue);
  const toggle = () => setValue(v => !v);
  return [value, toggle];
}

export default function ToggleComponent() {
  const [isOn, toggleIsOn] = useToggle();

  return (
    <div>
      <p>The switch is {isOn ? 'ON' : 'OFF'}</p>
      <button onClick={toggleIsOn} aria-pressed={isOn} aria-label="Toggle switch">
        Toggle
      </button>
    </div>
  );
}
OutputSuccess
Important Notes

Always start custom hook names with use so React knows they follow hook rules.

Custom hooks help keep your components clean by moving logic out.

Use accessibility attributes like aria-pressed on interactive elements for better keyboard and screen reader support.

Summary

Custom hooks let you reuse logic across components easily.

Name custom hooks starting with use.

They help keep components focused on UI and improve code organization.

Practice

(1/5)
1. What is the main reason to create a custom hook in React?
easy
A. To create new HTML elements
B. To reuse stateful logic across multiple components
C. To style components with CSS
D. To replace React components entirely

Solution

  1. Step 1: Understand the purpose of hooks

    Hooks let you use React features like state and effects inside functions.
  2. Step 2: Identify why custom hooks are used

    Custom hooks let you reuse stateful logic easily across components without repeating code.
  3. Final Answer:

    To reuse stateful logic across multiple components -> Option B
  4. Quick Check:

    Custom hooks = reuse logic [OK]
Hint: Custom hooks always reuse logic, not UI or styles [OK]
Common Mistakes:
  • Thinking custom hooks create UI elements
  • Confusing hooks with styling tools
  • Believing hooks replace components
2. Which of the following is the correct way to name a custom hook in React?
easy
A. hookUseFetch
B. fetchDataHook
C. FetchData
D. useFetchData

Solution

  1. Step 1: Recall naming rules for custom hooks

    Custom hooks must start with the word "use" to follow React conventions.
  2. Step 2: Check each option

    Only "useFetchData" starts with "use" correctly.
  3. Final Answer:

    useFetchData -> Option D
  4. Quick Check:

    Custom hook names start with "use" [OK]
Hint: Custom hooks always start with 'use' prefix [OK]
Common Mistakes:
  • Naming hooks without 'use' prefix
  • Using PascalCase without 'use'
  • Placing 'use' in the middle or end
3. Consider this custom hook code:
import { useState, useEffect } from 'react';

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return width;
}

What will useWindowWidth() return when used inside a component?
medium
A. The height of the browser window
B. An error because window is undefined
C. The current width of the browser window, updating on resize
D. A function to resize the window

Solution

  1. Step 1: Analyze the hook's state and effect

    The hook uses state to store window.innerWidth and updates it on resize events.
  2. Step 2: Understand the returned value

    The hook returns the current width, which updates whenever the window resizes.
  3. Final Answer:

    The current width of the browser window, updating on resize -> Option C
  4. Quick Check:

    Custom hook returns updated window width [OK]
Hint: Custom hooks return values or functions, not errors here [OK]
Common Mistakes:
  • Confusing width with height
  • Thinking it returns a function
  • Assuming window is undefined in browser
4. What is wrong with this custom hook code?
import { useState, useEffect } from 'react';

function useCounter() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    setCount(count + 1);
  });
  return count;
}
medium
A. It causes an infinite loop because setCount is called inside useEffect without dependencies
B. It returns a function instead of a value
C. It will never update count because useEffect has an empty dependency array
D. It uses useState incorrectly by initializing with 0

Solution

  1. Step 1: Check useEffect dependencies

    The effect has no dependency array.
  2. Step 2: Understand setCount behavior

    setCount(count + 1) runs on every render since there are no dependencies, causing an infinite loop of re-renders.
  3. Final Answer:

    It causes an infinite loop because setCount is called inside useEffect without dependencies -> Option A
  4. Quick Check:

    Missing deps in useEffect = infinite loop [OK]
Hint: useEffect without deps array runs every render [OK]
Common Mistakes:
  • Thinking the effect runs only once without deps array
  • Confusing return value type
  • Misunderstanding dependency array role
5. You want to create a custom hook useFetch that fetches data from a URL and returns { data, loading, error }. Which approach correctly handles loading state and errors inside the hook?
hard
A. Use useState for data, loading, error; use useEffect to fetch and update states with try/catch inside async function
B. Use only useState for data and ignore loading and error states
C. Fetch data directly in the component and pass it to the hook as a parameter
D. Use useEffect without useState and return data from fetch promise

Solution

  1. Step 1: Identify state needs for fetch

    Fetching data requires tracking data, loading status, and errors, so useState is needed for all three.
  2. Step 2: Use useEffect with async fetch and error handling

    Inside useEffect, define an async function with try/catch to fetch data and update states accordingly.
  3. Final Answer:

    Use useState for data, loading, error; use useEffect to fetch and update states with try/catch inside async function -> Option A
  4. Quick Check:

    Fetch with useState and useEffect + try/catch [OK]
Hint: Manage data, loading, error with useState and useEffect [OK]
Common Mistakes:
  • Ignoring loading or error states
  • Fetching outside useEffect causing infinite loops
  • Returning unresolved promises
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard