Interview

10 React Hook Interview Questions and Answers

Prepare for your next technical interview with this guide on React Hooks, featuring common questions and answers to enhance your understanding and skills.

React Hooks have revolutionized the way developers build and manage state in functional components. By allowing the use of state and other React features without writing a class, Hooks have simplified codebases and improved readability. This modern approach to React development has quickly become a standard practice, making it essential for developers to understand and utilize Hooks effectively.

This article provides a curated selection of interview questions focused on React Hooks. Reviewing these questions will help you deepen your understanding of Hooks, enhance your problem-solving skills, and prepare you to discuss this critical topic confidently in your next technical interview.

React Hook Interview Questions and Answers

1. How do you use the useState Hook to manage state in a functional component?

The useState Hook is a key part of React’s Hooks API, allowing functional components to manage state. It returns an array with the current state value and a function to update it.

Example:

import React, { useState } from 'react';

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

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

In this example, useState creates a state variable count and a function setCount to update it. The initial state is 0, and clicking the button increments the count.

2. Explain how the useEffect Hook works and provide an example of its usage.

The useEffect Hook manages side effects in React components. It takes a callback function and an optional array of dependencies. The effect runs after the initial render and whenever dependencies change.

Example:

import React, { useState, useEffect } from 'react';

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

    useEffect(() => {
        document.title = `You clicked ${count} times`;

        return () => {
            document.title = 'React App';
        };
    }, [count]);

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

Here, useEffect updates the document title whenever count changes, with a cleanup function to reset the title.

3. What is the purpose of the useReducer Hook and when would you use it over useState?

The useReducer hook is for managing complex state logic in React components. It is an alternative to useState when state transitions are intricate. It takes a reducer function and an initial state, returning the current state and a dispatch function.

Example:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

In this example, useReducer manages a counter’s state, with the reducer function handling state transitions.

4. Explain the useCallback Hook and provide a scenario where it would be useful.

The useCallback Hook memoizes a function, ensuring the same function instance is returned unless dependencies change. This is useful for preventing unnecessary re-renders when passing functions as props.

Example:

import React, { useState, useCallback } from 'react';

const ChildComponent = React.memo(({ onClick }) => {
    console.log('ChildComponent rendered');
    return <button onClick={onClick}>Click me</button>;
});

const ParentComponent = () => {
    const [count, setCount] = useState(0);

    const handleClick = useCallback(() => {
        console.log('Button clicked');
    }, []);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
            <ChildComponent onClick={handleClick} />
        </div>
    );
};

export default ParentComponent;

Here, handleClick is memoized, preventing ChildComponent from re-rendering unnecessarily.

5. Can you describe how custom Hooks work and provide an example of one you have created or might create?

Custom Hooks in React are functions that encapsulate reusable logic. They start with “use” and can call other Hooks.

Example:

import { useState, useEffect } from 'react';

function useFetch(url) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        fetch(url)
            .then(response => response.json())
            .then(data => {
                setData(data);
                setLoading(false);
            });
    }, [url]);

    return { data, loading };
}

// Usage in a component
function App() {
    const { data, loading } = useFetch('https://api.example.com/data');

    if (loading) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
    );
}

In this example, useFetch encapsulates data fetching logic, returning the data and loading state.

6. How would you handle asynchronous operations within a Hook, such as fetching data?

Handling asynchronous operations within a Hook, like fetching data, can be managed using useEffect with async/await syntax.

Example:

import React, { useState, useEffect } from 'react';

function DataFetchingComponent() {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        let isMounted = true;

        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                const result = await response.json();
                if (isMounted) {
                    setData(result);
                    setLoading(false);
                }
            } catch (error) {
                if (isMounted) {
                    console.error('Error fetching data:', error);
                    setLoading(false);
                }
            }
        };

        fetchData();

        return () => {
            isMounted = false;
        };
    }, []);

    if (loading) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
    );
}

export default DataFetchingComponent;

7. How can you share state between multiple components using Hooks?

Sharing state between components can be managed using useContext. Create a context and provide it at a higher level in your component tree. Components within this tree can access the shared state using useContext.

Example:

import React, { useState, useContext, createContext } from 'react';

const MyContext = createContext();

const MyProvider = ({ children }) => {
    const [sharedState, setSharedState] = useState('Initial State');
    return (
        <MyContext.Provider value={{ sharedState, setSharedState }}>
            {children}
        </MyContext.Provider>
    );
};

const ComponentA = () => {
    const { sharedState, setSharedState } = useContext(MyContext);
    return (
        <div>
            <p>Component A: {sharedState}</p>
            <button onClick={() => setSharedState('Updated State from A')}>Update from A</button>
        </div>
    );
};

const ComponentB = () => {
    const { sharedState } = useContext(MyContext);
    return <p>Component B: {sharedState}</p>;
};

const App = () => (
    <MyProvider>
        <ComponentA />
        <ComponentB />
    </MyProvider>
);

export default App;

8. How would you implement a Hook to debounce a function call?

Debouncing ensures a function is not called too frequently. In React, this can optimize performance, such as when handling user input events. A custom hook can debounce a function call.

Example:

import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
    const [debouncedValue, setDebouncedValue] = useState(value);

    useEffect(() => {
        const handler = setTimeout(() => {
            setDebouncedValue(value);
        }, delay);

        return () => {
            clearTimeout(handler);
        };
    }, [value, delay]);

    return debouncedValue;
}

// Usage example
import React, { useState } from 'react';

function SearchInput() {
    const [query, setQuery] = useState('');
    const debouncedQuery = useDebounce(query, 500);

    useEffect(() => {
        if (debouncedQuery) {
            console.log('Searching for:', debouncedQuery);
        }
    }, [debouncedQuery]);

    return (
        <input
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search..."
        />
    );
}

9. What is the difference between useEffect and useLayoutEffect and when would you use each?

useEffect and useLayoutEffect both allow side effects in React components but differ in timing. useEffect runs after the render is committed, while useLayoutEffect runs synchronously after DOM mutations but before the browser paints.

Example:

import React, { useEffect, useLayoutEffect, useState } from 'react';

const ExampleComponent = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        console.log('useEffect: After render');
    }, [count]);

    useLayoutEffect(() => {
        console.log('useLayoutEffect: Before paint');
    }, [count]);

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
};

In this example, useEffect logs after rendering, while useLayoutEffect logs before the paint.

10. Explain the useImperativeHandle Hook and provide a use case for it.

The useImperativeHandle hook customizes the instance value exposed to parent components when using ref. This is useful for controlling child component behavior from the parent without exposing the entire child component instance.

Example:

import React, { useImperativeHandle, useRef, forwardRef } from 'react';

const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} />;
});

const ParentComponent = () => {
  const childRef = useRef();

  const handleClick = () => {
    childRef.current.focus();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
};

export default ParentComponent;

In this example, ChildComponent uses useImperativeHandle to expose a focus method to the parent component.

Previous

15 Linux Shell Scripting Interview Questions and Answers

Back to Interview
Next

10 Windows Server Troubleshooting Interview Questions and Answers