
React hooks have transformed the way developers build components, offering a simpler and more maintainable approach to managing state and side effects. With React's widespread adoption, understanding hooks has become a key focus in developer interviews. Whether you're gearing up for an interview or brushing up on your skills, these 30 essential React hooks questions will guide you through both foundational concepts and advanced use cases.
If you're looking for more in-depth React interview preparation materials, also check out these resources:
React hooks are functions that allow developers to use state and other React features in functional components. Prior to hooks, these features were only available in class components. Hooks like useState, useEffect, and useContext are now central to modern React development.
Hooks allow you to use state and other React features in functional components, eliminating the need for classes. They simplify code by reducing reliance on lifecycle methods, improve code readability, and make it easier to reuse stateful logic across components. Common hooks like useState and useEffect help manage state and side effects.
React hooks must be called at the top level of a function, never inside loops, conditions, or nested functions. They should only be called from React function components or custom hooks. These rules help maintain correct state and lifecycle behavior.
useState?The useState hook allows you to add state to functional components. It returns an array with two elements: the current state value and a function to update it.
useState trigger re-renders?When the state update function from useState is called, React schedules the component to re-render. This re-render updates the Virtual DOM, compares it with the previous version, and applies the necessary changes to the actual DOM, ensuring the UI reflects the new state efficiently.
setState in useState?Yes, you can pass a function to setState in useState. The function receives the previous state value and returns the new state.
setState((prevState) => prevState + 1);
useEffect worksThe useEffect hook handles side effects like data fetching or DOM updates. It runs after rendering and is controlled by a dependencies array:
useEffect(() => {console.log('Effect ran');return () => console.log('Cleanup logic'); // Runs on unmount or dependency change}, [dependency]);
useEffect?[]): The effect runs only once, after the initial render.[a, b]): The effect runs whenever the specified dependencies change.useEffect?You can use useEffect to fetch data by calling an async function within the effect. Remember to handle loading and error states.
useEffect(() => {const fetchData = async () => {const response = await fetch('url');const data = await response.json();setData(data);};fetchData();}, []);
useEffect?To handle cleanup, return a function from the useEffect callback. This cleanup function is called when the component unmounts or when the dependencies change.
useEffect(() => {// Setup codereturn () => {// Cleanup code};}, [dependencies]);
useRef?The useRef hook creates a mutable object that persists through renders, allowing direct access to DOM elements, storing mutable values without causing re-renders, and maintaining references to values. For instance, useRef can be utilized to focus on an input element:
import React, { useRef, useEffect } from 'react';function TextInputWithFocusButton() {const inputEl = useRef(null);useEffect(() => {inputEl.current.focus();}, []);return <input ref={inputEl} type="text" />;}
useEffect and componentDidMount?useEffect runs after the initial render, while componentDidMount runs once after the component is mounted. However, useEffect is more flexible as it can handle dependencies.
useContext?The useContext hook allows you to access the value of a context in a functional component. It eliminates the need to pass props down multiple layers.
useId hook in React and when should it be used?The useId hook generates unique IDs for elements within a component, which is crucial for accessibility by linking form inputs with labels. It guarantees unique IDs across the application even if the component renders multiple times.
import { useId } from 'react';function MyComponent() {const id = useId();return (<div><label htmlFor={id}>Name:</label><input id={id} type="text" /></div>);}
Custom hooks are JavaScript functions that allow you to reuse stateful logic across multiple components. They can use built-in hooks like useState, useEffect, etc., and encapsulate logic that can be shared.
useReducer over useState?useReducer is helpful when managing complex state logic, especially when the state depends on previous values or when state updates are tied to specific actions.
useMemo work?The useMemo hook is used to memoize expensive calculations so they only rerun when specific dependencies change. This can improve performance, especially in large applications.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo and useCallback?useMemo is used to memoize the result of a function, while useCallback is used to memoize the function itself. Both are useful for preventing unnecessary re-renders.
useMemo over useCallback?Use useMemo to memoize the results of calculations, and use useCallback to memoize the function itself. useMemo is used for computations, while useCallback is used for functions passed down as props.
useImperativeHandle hook used for?useImperativeHandle customizes the instance value that is exposed to parent components when using ref. This allows you to control which methods or properties are available when the parent component accesses the ref.
useDeferredValue improve UI responsiveness?useDeferredValue defers updates to a value, prioritizing smoother UI interactions.
useTransition?useTransition manages state transitions with a lower priority, useful for rendering smooth updates.
useEffect and useLayoutEffect?useEffect and useLayoutEffect are both used for handling side effects in React functional components but differ in timing:
useEffect runs asynchronously after the DOM has painted, ideal for tasks like data fetching or subscriptions.useLayoutEffect runs synchronously after DOM mutations but before the browser paints, useful for tasks like measuring DOM elements or synchronizing the UI with the DOM.Code Example:
import React, { useEffect, useLayoutEffect, useRef } from 'react';function Example() {const ref = useRef();useEffect(() => {console.log('useEffect: Runs after DOM paint');});useLayoutEffect(() => {console.log('useLayoutEffect: Runs before DOM paint');console.log('Element width:', ref.current.offsetWidth);});return <div ref={ref}>Hello</div>;}
useCallback?useCallback is used to memoize functions so that they don't get recreated on every render. This is especially useful when passing callbacks to child components to prevent unnecessary re-renders.
const memoizedCallback = useCallback(() => {doSomething(a, b);}, [a, b]);
useReducer work?The useReducer hook is an alternative to useState for handling more complex state logic. It works similarly to Redux reducers, where an action is dispatched to update the state.
const [state, dispatch] = useReducer(reducer, initialState);
useLayoutEffect?useLayoutEffect is used for DOM mutations that need to be applied before the paint, ensuring that the component is fully updated before the browser renders the changes.
To prevent unnecessary re-renders:
React.memo to memoize functional components.useMemo to memoize calculations.useCallback to memoize event handlers.Custom hooks allow you to encapsulate and reuse stateful logic. For example, a useFetch hook could handle data fetching logic for multiple components.
const useFetch = (url) => {const [data, setData] = useState(null);useEffect(() => {fetch(url).then((res) => res.json()).then(setData);}, [url]);return data;};
setState() in React and when should it be used?The callback function format of setState() in React ensures that state updates are based on the most current state and props. This is essential when the new state depends on the previous state. Instead of passing an object directly to setState(), you provide a function that takes the previous state and props as arguments, returning the updated state.
this.setState((prevState, props) => ({counter: prevState.counter + props.increment,}));
Using this approach helps avoid issues related to asynchronous updates, ensuring that your state reflects the latest values accurately.