React js Custom Hooks Practice Questions with Solutions

Introduction

Custom Hooks in React are reusable JavaScript functions that allow you to share stateful logic between multiple components. A Custom Hook can use built-in Hooks such as useState, useEffect, and useRef, or even other Custom Hooks. Custom Hooks usually start with the word use. In this chapter, we will solve practical questions to understand how to create, use, and reuse Custom Hooks in React applications. React js Custom Hooks practice questions help to understand the concepts.

1. What are Custom Hooks in React?

Custom Hooks are JavaScript functions that allow you to reuse logic that uses React Hooks across different components.

A Custom Hook usually starts with use, for example:

function useCounter() {
  // Hook logic
}

Custom Hooks can use built-in Hooks such as:

useState()
useEffect()
useRef()

For example:

function useCounter() {
  const [count, setCount] = useState(0);

  return count;
}

The main purpose of Custom Hooks is logic reuse, not sharing the same state between components.


2. Why are Custom Hooks used in React?

Custom Hooks are mainly used to avoid repeating the same stateful logic in multiple components.

For example, suppose two components need the same counter logic.

Instead of writing the same code twice, we can create:

function useCounter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(c => c + 1);
  };

  return { count, increment };
}

Now different components can use this logic:

function CounterOne() {
  const { count, increment } = useCounter();

  return (
    <>
      <p>{count}</p>
      <button onClick={increment}>+</button>
    </>
  );
}

Another component can use the same Hook:

function CounterTwo() {
  const { count, increment } = useCounter();

  return (
    <>
      <p>{count}</p>
      <button onClick={increment}>+</button>
    </>
  );
}

This makes React applications easier to maintain and organize.


3. What are the Rules for creating Custom Hooks?

Custom Hooks follow the same Rules of Hooks as built-in Hooks.

Important rules include:

  1. The function should normally start with use.
  2. Hooks should be called only at the top level.
  3. Do not call Hooks inside loops or conditions.
  4. Hooks can be called inside React function components or other Custom Hooks.
  5. A Custom Hook can call other Hooks.

Correct example:

function useUser() {
  const [user, setUser] = useState(null);

  return { user, setUser };
}

Avoid this:

function useUser(isLoggedIn) {
  if (isLoggedIn) {
    const [user, setUser] = useState(null);
  }
}

The Hook call should not be placed conditionally.


4. How do you create a simple Custom Hook?

Let’s create a simple Custom Hook that returns a message.

function useMessage() {
  return "Welcome to React";
}

We can use it inside a component:

function App() {
  const message = useMessage();

  return <h2>{message}</h2>;
}

Complete example:

import React from "react";

function useMessage() {
  return "Welcome to React";
}

function App() {
  const message = useMessage();

  return <h2>{message}</h2>;
}

export default App;

Here, useMessage() is a Custom Hook.


5. How do you create a Custom Hook with useState?

A Custom Hook can use useState() to manage stateful logic.

Example:

import { useState } from "react";

function useCounter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(c => c + 1);
  };

  return {
    count,
    increment
  };
}

We can use it inside a component:

function Counter() {
  const { count, increment } = useCounter();

  return (
    <div>
      <h2>{count}</h2>
      <button onClick={increment}>Increase</button>
    </div>
  );
}

The Custom Hook contains the counter logic, while the component focuses on displaying the UI.


6. How do you create a Custom Hook with useEffect?

Custom Hooks can also use useEffect() when the reusable logic needs synchronization with an external system.

For example:

import { useEffect, useState } from "react";

function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
  }, [title]);
}

Now a component can use it:

function Profile() {
  useDocumentTitle("Profile");

  return <h2>Profile Page</h2>;
}

Another component can use the same Hook:

function About() {
  useDocumentTitle("About");

  return <h2>About Page</h2>;
}

This avoids repeating the document-title effect in every component.


7. How do you pass parameters to a Custom Hook?

Custom Hooks can accept parameters just like normal JavaScript functions.

Example:

import { useState } from "react";

function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);

  const increment = () => {
    setCount(c => c + 1);
  };

  return {
    count,
    increment
  };
}

Now we can provide different initial values:

function App() {
  const counterOne = useCounter(0);
  const counterTwo = useCounter(10);

  return (
    <>
      <h2>Counter 1: {counterOne.count}</h2>
      <button onClick={counterOne.increment}>Increase</button>

      <h2>Counter 2: {counterTwo.count}</h2>
      <button onClick={counterTwo.increment}>Increase</button>
    </>
  );
}

The parameter allows the Custom Hook to be more flexible and reusable.


8. How do you return multiple values or functions from a Custom Hook?

A Custom Hook can return an object or an array containing multiple values and functions.

Example:

import { useState } from "react";

function useCounter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(c => c + 1);
  };

  const decrement = () => {
    setCount(c => c - 1);
  };

  const reset = () => {
    setCount(0);
  };

  return {
    count,
    increment,
    decrement,
    reset
  };
}

The component can destructure these values:

function Counter() {
  const {
    count,
    increment,
    decrement,
    reset
  } = useCounter();

  return (
    <div>
      <h2>{count}</h2>

      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Returning an object is useful when a Custom Hook provides several related values and functions.


9. How do you reuse a Custom Hook in multiple components?

A Custom Hook can be called by multiple components.

For example:

import { useState } from "react";

function useCounter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(c => c + 1);
  };

  return { count, increment };
}

Component 1:

function CounterOne() {
  const { count, increment } = useCounter();

  return (
    <>
      <h2>Counter One: {count}</h2>
      <button onClick={increment}>+</button>
    </>
  );
}

Component 2:

function CounterTwo() {
  const { count, increment } = useCounter();

  return (
    <>
      <h2>Counter Two: {count}</h2>
      <button onClick={increment}>+</button>
    </>
  );
}

Each component gets its own state.

So, if CounterOne has a count of 5, that does not automatically make CounterTwo‘s count 5.

Custom Hooks share logic, not one shared state instance.


10. How do you build a practical useCounter Custom Hook?

Let’s create a complete reusable useCounter Hook.

import { useState } from "react";

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => {
    setCount(c => c + 1);
  };

  const decrement = () => {
    setCount(c => c - 1);
  };

  const reset = () => {
    setCount(initialValue);
  };

  return {
    count,
    increment,
    decrement,
    reset
  };
}

Now use it in a component:

function Counter() {
  const {
    count,
    increment,
    decrement,
    reset
  } = useCounter(5);

  return (
    <div>
      <h2>Count: {count}</h2>

      <button onClick={increment}>Increase</button>
      <button onClick={decrement}>Decrease</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

export default Counter;

How it works

  • useCounter(5) starts the counter at 5.
  • increment() increases the count.
  • decrement() decreases the count.
  • reset() returns the count to the initial value.
  • The same Hook can be reused by other components.

This is a practical example of how Custom Hooks help separate reusable logic from UI.

Key Takeaways

  • Custom Hooks are reusable JavaScript functions that use React Hooks.
  • Custom Hook names normally start with use.
  • Custom Hooks can use built-in Hooks such as useState, useEffect, and useRef.
  • Custom Hooks help reuse stateful logic between components.
  • Each call to a Custom Hook has its own independent state.
  • Custom Hooks share logic, not automatically the same state.
  • Hooks must follow the Rules of Hooks.
  • Custom Hooks can accept parameters.
  • Custom Hooks can return values, objects, arrays, and functions.
  • useCounter is a simple and useful example of a reusable Custom Hook.

FAQs

1. What is a Custom Hook in React?

A Custom Hook is a reusable JavaScript function that can use React Hooks to share stateful logic between components.

2. Why do we use Custom Hooks in React?

Custom Hooks are used to reuse logic and avoid writing the same stateful logic repeatedly in different components.

3. Do Custom Hooks share the same state?

No. Each call to a Custom Hook creates its own independent state. Custom Hooks share logic, not automatically one shared state.

4. Can a Custom Hook use useState?

Yes. A Custom Hook can use useState() to manage reusable stateful logic.

5. Can a Custom Hook use useEffect?

Yes. A Custom Hook can use useEffect() when the reusable logic needs an effect or synchronization with an external system.

6. What should the name of a Custom Hook start with?

Custom Hook names should normally start with use, such as useCounter, useFetch, useToggle, or useDocumentTitle.

7. Can one Custom Hook use another Custom Hook?

Yes. A Custom Hook can call built-in Hooks and other Custom Hooks, as long as the Rules of Hooks are followed.

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top