Top 50+ ReactJS Interview Questions (2025)

Amit PandeyAmit Pandey
17 min read

Table of contents

ReactJS, one of the most popular JavaScript libraries for building user interfaces, continues to evolve. As the demand for React developers grows, it’s essential to understand the key concepts, hooks, and advanced patterns that are used in React development. In this blog, we’ll answer more than 50 essential ReactJS interview questions in detail, providing examples to help you understand how these features work.

1. What are React Hooks?

React Hooks are functions that allow you to use state and other React features without writing a class component. Hooks were introduced in React 16.8 to make it easier to manage state, side-effects, context, and more in functional components.

Example:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

2. What are the advantages of using hooks over class components?

Hooks offer several advantages over class components:

  • Simplicity: Functional components are easier to write and understand compared to class components.

  • Reusability: Hooks allow for better code reuse by enabling the creation of custom hooks.

  • No this keyword: With hooks, you don’t need to worry about binding this to methods in the component.

  • Performance: Hooks can help improve performance by avoiding unnecessary re-renders that happen with class components.

3. What is the useState hook?

useState is a hook that lets you add state to a functional component. It returns an array with two elements: the current state value and a function to update it.

Example:

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

4. What is the useEffect hook?

useEffect is a hook used to perform side effects in a functional component, such as fetching data, updating the DOM, or subscribing to external data sources.

Example:

useEffect(() => {
  console.log('Component mounted or updated');
}, []);

5. What are some use cases for useEffect?

useEffect can be used in the following scenarios:

  • Fetching data: Triggering API calls.

  • Subscribing to external events: Like WebSocket connections.

  • Updating the document title: Based on a state change.

6. What is useContext and how does it work?

useContext is a hook that allows you to access the value of a context without having to pass it through props manually.

Example:

const ThemeContext = React.createContext('light');

function ThemedComponent() {
  const theme = useContext(ThemeContext);
  return <div>{theme}</div>;
}

7. What is the useReducer hook and when would you use it?

useReducer is a hook used for managing more complex state logic in functional components, especially when dealing with multiple state values or complex state transitions.

Example:

const initialState = { count: 0 };
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

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

8. What is the useMemo hook?

useMemo is a hook that memoizes the result of an expensive function call, preventing it from being re-executed on every render unless its dependencies change.

Example:

const expensiveValue = useMemo(() => expensiveComputation(value), [value]);

9. What is React.memo()?

React.memo() is a higher-order component (HOC) that memorizes a functional component’s output, preventing unnecessary re-renders if the props haven’t changed.

Example:

const MemoizedComponent = React.memo(MyComponent);

10. What is the useCallback hook?

useCallback is a hook that memoizes a function so that it is not re-created on every render unless its dependencies change.

Example:

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

11. What are the rules of hooks?

Hooks must follow these rules:

  • Call hooks at the top level: Don’t call hooks inside loops, conditions, or nested functions.

  • Call hooks only from React function components or custom hooks.

12. What is the useRef hook and how does it differ from useState?

useRef is used to persist a value across renders without causing re-renders. It’s useful for accessing DOM elements or storing mutable values.

Example:

const inputRef = useRef(null);

13. What is useLayoutEffect and how is it different from useEffect?

useLayoutEffect runs synchronously after the DOM has been updated but before the browser paints. It is useful for DOM mutations that must be performed before rendering.

14. What are custom hooks in React?

Custom hooks are JavaScript functions that allow you to reuse logic across different components. They follow the same rules as React’s built-in hooks but provide custom functionality.

Example:

function useCustomHook() {
  const [count, setCount] = useState(0);
  return { count, setCount };
}

15. What is useImperativeHandle and how does it work?

useImperativeHandle allows you to customize the instance value that is exposed when using ref on a functional component.

Example:

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

16. What are Controlled vs Uncontrolled components?

  • Controlled components: The component’s state is managed by React via props.

  • Uncontrolled components: The component manages its own state internally using ref.

17. What is a Higher Order Component?

A Higher-Order Component (HOC) is a function that takes a component and returns a new component with additional props or functionality.

Example:

function withAuth(Component) {
  return function AuthHOC(props) {
    // Add authentication logic here
    return <Component {...props} />;
  };
}

18. What is a virtual DOM, how is it different from a real DOM and how does it work?

The virtual DOM is a lightweight copy of the actual DOM. React uses it to optimize rendering by diffing the virtual DOM and updating only the changed elements in the real DOM.

19. What is the difference between componentDidMount and useEffect?

componentDidMount is a lifecycle method in class components that runs once after the component mounts. useEffect can mimic componentDidMount by passing an empty dependency array ([]), but it also handles side effects in functional components.

20. What is React Fragments?

Fragments allow you to group a list of children without adding extra nodes to the DOM.

Example:

return (
  <>
    <h1>Title</h1>
    <p>Content</p>
  </>
);

21. What is JSX?

JSX is a syntax extension for JavaScript that allows you to write HTML-like code in JavaScript. It is used by React to describe the UI.

Example:

const element = <h1>Hello, world!</h1>;

22. What is prop and what is prop drilling and what is the solution to avoid prop drilling?

A prop is a mechanism for passing data from a parent component to a child component. Prop drilling refers to passing props through multiple levels of components. To avoid prop drilling, you can use Context API or state management libraries like Redux.

23. What is Context in React?

Context allows you to share values across the component tree without having to pass props manually through each level.

Example:

const ThemeContext = React.createContext('light');

24. What are various ways to style a React app?

You can style a React app using:

  • CSS Files

  • CSS-in-JS (Styled Components, Emotion)

  • Inline Styles

  • SASS/SCSS

  • CSS Modules

25. What are render props in React?

Render props is a pattern where a component’s function accepts a function as a prop, which is used to render UI elements.

Example:

function DataProvider({ render }) {
  return render('data');
}

<DataProvider render={(data) => <h1>{data}</h1>} />

26. What are the key features of React?

React offers several key features that make it one of the most popular libraries for building modern web applications:

  • Declarative UI: React allows developers to describe what the UI should look like based on state, making it more predictable and easier to debug.

  • Component-based Architecture: React allows building UIs using components, which can be reused, making development more modular.

  • Virtual DOM: React uses a virtual DOM to optimize UI updates. Only changed components are updated in the real DOM, leading to faster rendering.

  • Unidirectional Data Flow: Data flows in one direction, making the app more predictable and easier to debug.

  • Hooks: React introduced hooks in version 16.8, allowing developers to use state and lifecycle features in functional components.

  • React Native: React can be used for mobile app development through React Native, which is based on the same principles as React for the web.

27. What are components in React?

Components are the building blocks of a React application. They define how the UI should look and behave. React components can either be functional components or class components.

Example of a Functional Component:

function HelloWorld() {
  return <h1>Hello, World!</h1>;
}

28. What is the difference between functional and class components?

  • Functional Components: Simpler and more concise, functional components are defined as functions. They can use hooks (like useState, useEffect) to manage state and side effects.

    Example:

      function MyComponent() {
        const [count, setCount] = useState(0);
        return <div>{count}</div>;
      }
    
  • Class Components: Class components use ES6 classes and manage state with this.state. They have lifecycle methods like componentDidMount, componentDidUpdate, etc.

    Example:

      class MyComponent extends React.Component {
        state = { count: 0 };
    
        render() {
          return <div>{this.state.count}</div>;
        }
      }
    

29. What are props in React?

Props (short for properties) are used to pass data from a parent component to a child component. They are immutable, meaning that a child component cannot modify the props it receives.

Example:

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

function App() {
  return <Greeting name="John" />;
}

30. What is state in React?

State is an object that holds data or information about the component. State can change over time and when it does, React re-renders the component to reflect the changes.

Example:

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

31. What is the difference between state and props?

  • State: State is managed within a component and can change over time. State is mutable.

  • Props: Props are passed down from a parent component and are immutable. A child component cannot modify its props.

32. What are keys in React, and why are they important?

Keys are special props used in lists to identify each element uniquely. They help React efficiently update and re-render lists by tracking which items changed, were added, or removed.

Example:

const items = ['apple', 'banana', 'cherry'];
const listItems = items.map((item, index) => <li key={index}>{item}</li>);

33. What is React Router?

React Router is a library used to handle routing in React applications. It allows for navigation between different components or pages without reloading the entire page.

Example:

import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Link to="/home">Home</Link>
      <Route path="/home" component={Home} />
    </Router>
  );
}

34. What is the Context API?

The Context API provides a way to share values like themes, authentication status, or language preferences across the component tree without passing props manually through every level.

Example:

const ThemeContext = React.createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ChildComponent />
    </ThemeContext.Provider>
  );
}

function ChildComponent() {
  const theme = useContext(ThemeContext);
  return <div>{theme}</div>;
}

35. What is Redux, and why is it used?

Redux is a state management library for JavaScript apps, commonly used with React. It provides a central store for managing the state of the entire application, making state changes more predictable.

  • Used for: Handling global state in large applications.

  • Core concepts: Store, Actions, Reducers.

Example:

// Redux store setup
import { createStore } from 'redux';

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

const store = createStore(reducer);

36. What is the difference between useState and useReducer?

  • useState: Ideal for simple state changes. It provides a function to update the state.

  • useReducer: Used for managing more complex state logic, especially when multiple state variables need to be updated together. It works with actions and reducers, similar to Redux.

Example:

// useState
const [count, setCount] = useState(0);

// useReducer
const initialState = { count: 0 };
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    default:
      return state;
  }
}
const [state, dispatch] = useReducer(reducer, initialState);

37. What are render props?

Render props is a pattern where a component’s function accepts a function as a prop, which is used to render UI elements. It allows a component to share state or logic with another component.

Example:

function DataProvider({ render }) {
  return render('data');
}

<DataProvider render={(data) => <h1>{data}</h1>} />

38. What is code splitting in React?

Code splitting is a technique used to split the bundle of JavaScript files into smaller chunks, allowing for faster load times. React supports lazy loading with React.lazy and Suspense.

Example:

const MyComponent = React.lazy(() => import('./MyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <MyComponent />
    </Suspense>
  );
}

39. What are error boundaries in React?

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree and display a fallback UI instead of crashing the whole application.

Example:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

40. What is the difference between useMemo and useCallback?

  • useMemo: Memoizes the result of a function so that it’s only recomputed when the dependencies change.

  • useCallback: Memoizes the function itself, ensuring the function reference remains the same unless the dependencies change.

Example:

const memoizedValue = useMemo(() => expensiveComputation(), [dependencies]);
const memoizedCallback = useCallback(() => { console.log('Action'); }, [dependencies]);

41. How does React handle performance optimization?

React optimizes performance using several techniques, including:

  • Virtual DOM: Minimizes direct updates to the real DOM.

  • React.memo: Prevents unnecessary re-renders of functional components.

  • PureComponent: Prevents re-renders if props and state are unchanged.

  • Code splitting: Reduces the initial load time.

42. What is the difference between React.PureComponent and React.Component?

  • React.Component: A base class for creating components. It re-renders the component on every state or prop change.

  • React.PureComponent: Extends React.Component but implements shouldComponentUpdate() with a shallow prop and state comparison, preventing unnecessary re-renders.

43. What is server-side rendering (SSR) in React?

Server-side rendering (SSR) is a technique where React components are rendered on the server, and the resulting HTML is sent to the client. This can improve performance, SEO, and time-to-interactive.

44. What is the difference between createElement and cloneElement?

  • createElement: Used to create a new React element from a type and props.

  • cloneElement: Used to clone an existing React element, optionally modifying its props.

45. How do you test React components?

You can test React components using tools like Jest and React Testing Library. Common methods include:

  • Rendering components in a test environment.

  • Simulating events (e.g., clicks, form submissions).

  • Asserting changes in the DOM or component behavior.


Practical Examples

46. Create a simple counter component using useState:

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

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

47. Fetch data from an API and display it using useEffect:

function DataFetcher() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      {data.map(post => <p key={post.id}>{post.title}</p>)}
    </div>
  );
}

48. Implement a Search Filter for a List of Items

A search filter is a common feature in applications where users need to find specific items in a list. Below is an example of how to implement a search filter for a list of items in React.

Example:

import React, { useState } from 'react';

function ItemList() {
  const [searchTerm, setSearchTerm] = useState('');
  const items = ['Apple', 'Banana', 'Orange', 'Grapes', 'Pineapple'];

  const handleSearchChange = (e) => {
    setSearchTerm(e.target.value);
  };

  const filteredItems = items.filter(item => 
    item.toLowerCase().includes(searchTerm.toLowerCase())
  );

  return (
    <div>
      <input
        type="text"
        placeholder="Search items"
        value={searchTerm}
        onChange={handleSearchChange}
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

In this example, the useState hook is used to manage the search term, and filter() is used to filter the list of items based on the user's input.


49. Write a Higher-Order Component (HOC) to Log Component Props

A Higher-Order Component (HOC) is a pattern that allows you to add additional functionality to an existing component without modifying its code directly. Below is an example of an HOC that logs the props passed to a component.

Example:

import React from 'react';

function withLogger(WrappedComponent) {
  return function(props) {
    console.log('Current Props:', props);
    return <WrappedComponent {...props} />;
  };
}

function MyComponent({ name, age }) {
  return (
    <div>
      <h1>{name}</h1>
      <p>{age}</p>
    </div>
  );
}

const MyComponentWithLogger = withLogger(MyComponent);

function App() {
  return <MyComponentWithLogger name="John" age={30} />;
}

In this example, the withLogger HOC takes a component (MyComponent) and returns a new component that logs the props each time it renders.


50. Create a Form with Validation Using Controlled Components

Controlled components allow you to manage the form's state within the component itself. Below is an example of creating a simple form with validation using controlled components.

Example:

import React, { useState } from 'react';

function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!name || !email) {
      setError('Both fields are required');
    } else {
      setError('');
      alert(`Name: ${name}, Email: ${email}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Name</label>
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </div>
      <div>
        <label>Email</label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </div>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <button type="submit">Submit</button>
    </form>
  );
}

In this example:

  • useState is used to manage the form data (name, email) and error message.

  • The handleSubmit function validates the form and displays an error message if fields are empty.


51. Implement Routing Using React Router

React Router is used to handle navigation within a React application. Below is an example of how to implement routing using React Router.

Example:

import React from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';

function Home() {
  return <h2>Home Page</h2>;
}

function About() {
  return <h2>About Page</h2>;
}

function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
        </ul>
      </nav>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </Router>
  );
}

In this example, BrowserRouter (alias Router) is used to enable routing. The Switch component ensures only one route is matched, and Link components are used to navigate between different pages.


52. Use the Context API to Share a Theme Across the Application

The Context API allows you to share state globally across components without passing props manually. Here’s how you can use the Context API to share a theme.

Example:

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

const ThemeContext = createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

function ThemedComponent() {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <div style={{ backgroundColor: theme === 'light' ? 'white' : 'black' }}>
      <p>The current theme is {theme}</p>
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        Toggle Theme
      </button>
    </div>
  );
}

function App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>
  );
}

In this example, the ThemeContext is created and used to pass down the current theme and a function to toggle it across components without passing props manually.


53. Optimize a Component Using React.memo or useMemo

React provides React.memo and useMemo to optimize performance by memoizing the result of a component or function, respectively.

Example using React.memo:

const MyComponent = React.memo(function MyComponent({ name }) {
  console.log('Rendering:', name);
  return <h1>{name}</h1>;
});

function App() {
  return <MyComponent name="John" />;
}

In this example, MyComponent will only re-render if the name prop changes, thus optimizing the performance.

Example using useMemo:

const expensiveValue = useMemo(() => expensiveComputation(), [dependencies]);

useMemo ensures that the expensive computation is not recalculated unless the dependencies change.


54. Write a Custom Hook to Fetch Data

Custom hooks allow you to encapsulate logic in a reusable way. Below is an example of a custom hook to fetch data from an API.

Example:

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

Usage:

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

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

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

55. Implement a Redux Store and Connect it to a React Component

Redux is used to manage global application state. Below is an example of setting up a Redux store and connecting it to a React component.

Example:

  1. Set up the Redux store:
import { createStore } from 'redux';

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

const store = createStore(reducer);
  1. Connect React component to Redux store:
import React from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';

function Counter() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
    </div>
  );
}

function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}

In this example, Provider is used to make the Redux store available to the components, and useSelector and useDispatch are used to interact with the store in functional components.


0
Subscribe to my newsletter

Read articles from Amit Pandey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Amit Pandey
Amit Pandey