React JS Interview Questions and Answers With Examples (2025)

Before diving into React interview questions, your fundamentals must be solid. If you’re shaky on HTML, CSS, or JavaScript, you’re going to struggle with real-world React code, let alone interviews. Ensure you spend time mastering the core building blocks of the frontend before delving into React-specific concepts.
That said, let’s walk through some of the most frequently asked React.js interview questions. Each one covers not just the “what,” but the “why,” and includes code examples to help you understand how it works.
At a high level, we will cover:
- Core React Interview Questions
- React Router Questions
- React Testing Questions
- State Management Questions
- React Performance Questions
This chapter goes deep on the core topics. For a wider question bank, including hooks, React 19, Server Components, and senior-level questions, see 300+ React interview questions and answers.
Let’s begin!
Core React Interview Questions
What are props and state in React, and what’s the difference?
Props are read-only values passed from a parent component to a child. State is local data managed within an element itself. Props are immutable from the child’s perspective, while state can be updated via hooks like useState.
// Functional component with both props and state
import React, { useState } from "react";
function Counter({ title }) {
const [count, setCount] = useState(0); // state: owned by this component
return (
<div>
<h2>{title}</h2> {/* prop: passed from parent */}
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
What is the Virtual DOM, and how does it work?
The Virtual DOM is an in-memory representation of the actual Document Object Model (DOM). When state or props change, React creates a new virtual DOM tree, compares it with the previous one (diffing), and updates only the parts of the real DOM that changed, minimizing expensive DOM operations.
What is React Fiber, and what are its main goals?
React Fiber is the internal engine behind React’s rendering. It allows React to break rendering work into small units and pause or resume it, improving responsiveness for complex UI updates. Its primary goals are concurrency, interruptible rendering, and better scheduling.
What are Higher-Order Components (HOCs) in React?
A Higher-Order Component is a function that takes a component and returns a new element with enhanced behavior. It’s a typical pattern for code reuse.
// A simple HOC that adds a "theme" prop
function withTheme(Component) {
return function ThemedComponent(props) {
return <Component {...props} theme="dark" />;
};
}
function Button(props) {
return <button className={props.theme}>Click</button>;
}
const ThemedButton = withTheme(Button);
What’s the difference between useMemo and useCallback?
useMemo caches a computed value; useCallback caches a function. Use useMemo when you want to avoid expensive recalculations (see the useMemo docs). Use useCallback when you want to avoid re-creating a function on every render.
import React, { useMemo, useCallback, useState } from "react";
function Example({ items }) {
const [count, setCount] = useState(0);
// Cached sorted items (useMemo)
const sorted = useMemo(() => {
return [...items].sort();
}, [items]);
// Cached click handler (useCallback)
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<button onClick={handleClick}>Increment</button>
<ul>{sorted.map(i => <li key={i}>{i}</li>)}</ul>
</div>
);
}
How do you memoize a component and why?
Use React.memo to memoize functional components. It prevents unnecessary re-renders when props haven’t changed. This is useful for optimizing performance, especially in large lists or deeply nested UIs.
const Greeting = React.memo(function Greeting({ name }) {
console.log("Rendered!");
return <p>Hello, {name}!</p>;
});
// Will only re-render if `name` changes
How do you loop inside JSX to create elements?
You can loop using JavaScript’s map() function to generate JSX dynamically. This is commonly used to render lists.
function List({ items }) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
Why should you not update props in React?
Props are meant to be immutable — the parent component controls them. Updating props inside a child breaks the unidirectional data flow in React and can cause unpredictable bugs.
// ❌ Never do this
function MyComponent(props) {
props.title = "New Title"; // Invalid
}
Can you use async/await In React?
Yes. You can use async/await inside event handlers, or inside useEffect (just not directly in the effect function — you must define an async function inside it).
import { useEffect, useState } from "react";
function UserProfile() {
const [user, setUser] = useState(null);
useEffect(() => {
async function fetchUser() {
const res = await fetch("/api/user");
const data = await res.json();
setUser(data);
}
fetchUser(); // Call the async function
}, []);
return user ? <p>Hello {user.name}</p> : <p>Loading...</p>;
}
What are the most commonly used hooks in React?
React provides a number of built-in hooks to manage state, side effects, and performance. Some of the most commonly used ones include:
useState– For managing local stateuseEffect– For running side effects after renderuseMemo– For memoizing expensive valuesuseCallback– For memoizing functionsuseRef– For persisting values between renders (without re-rendering)useContext– For accessing context across your component tree
What are custom hooks and when should you use them?
Custom hooks let you extract reusable logic from components into separate functions that can be reused across your app. They follow the same rules as built-in hooks and start with the word use.
// Custom hook to get current window width
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;
}
// Usage
function App() {
const width = useWindowWidth();
return <p>Current width: {width}px</p>;
}
What’s the difference between functional and class-based components?
Class components use class syntax and require you to use this, while functional components are simpler, more concise, and use hooks for state and lifecycle logic. As of today, functional components are the standard in modern React.
// Class component
class Greeting extends React.Component {
render() {
return <p>Hello {this.props.name}</p>;
}
}
// Functional component (preferred)
function Greeting({ name }) {
return <p>Hello {name}</p>;
}
Why does the virtual DOM exist?
The virtual DOM exists to improve performance and simplify UI updates. Manipulating the real DOM is slow. React batches updates in a virtual DOM (a lightweight JS object), then figures out the minimal set of changes needed, and updates the real DOM efficiently.
What are error boundaries in React?
Error boundaries are React components that catch JavaScript errors in their child components and display a fallback UI instead of breaking the app. You can only define error boundaries using class components (see the React docs on error boundaries).
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error("Caught error:", error);
}
render() {
if (this.state.hasError) {
return <h2>Something went wrong.</h2>;
}
return this.props.children;
}
}
What are React lifecycle methods (or hook equivalents)?
In class components, lifecycle methods include:
componentDidMountcomponentDidUpdatecomponentWillUnmount
In functional components, the equivalent is the useEffect hook.
// Equivalent of componentDidMount
useEffect(() => {
console.log("Component mounted");
}, []);
What happens if the dependency array in useEffect is empty?
If the dependency array is empty [], the effect runs only once after the first render — like componentDidMount. If you omit the dependency array entirely, the effect runs on every render, which can lead to performance issues.
What is a ref in React, and why is it useful?
A ref is a way to access and interact with DOM elements or store a mutable value without triggering a re-render. Useful for focusing inputs, measuring layout, or storing timeouts.
import { useRef, useEffect } from "react";
function InputFocus() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus(); // Access DOM node directly
}, []);
return <input ref={inputRef} />;
}
What is useContext and when would you use it?
useContext gives you access to values provided by a React Context provider without the need for prop drilling. Use it when you need to share state across multiple components (such as themes or authentication).
// Create context
const ThemeContext = React.createContext("light");
// Use it in a component
function ThemeLabel() {
const theme = React.useContext(ThemeContext);
return <p>Current theme: {theme}</p>;
}
// Wrap part of the app
<ThemeContext.Provider value="dark">
<ThemeLabel />
</ThemeContext.Provider>
What are the different phases of a React component’s lifecycle?
React components go through these phases:
- Mounting – Component is created and added to the DOM
- Updating – Component re-renders due to props or state change
- Unmounting – Component is removed from the DOM
In functional components, you use useEffect with dependencies to handle each phase. You can return a cleanup function from useEffect to mimic componentWillUnmount.
useEffect(() => {
// Mounting
console.log("Component mounted");
// Cleanup
return () => {
console.log("Component unmounted");
};
}, []);
React Router Interview Questions
What is the purpose of push and replace in React Router history?
The history.push() and history.replace() methods let you navigate programmatically in React Router. The difference is:
push()adds a new entry to the history stack (user can go back).replace()replaces the current entry (user can’t go back).
history.push("/dashboard"); // Navigate to dashboard, keep history
history.replace("/login"); // Navigate to login, replace current entry
How do you programmatically navigate using React Router 4+?
You can use the useNavigate hook in React Router v6+ or the useHistory hook in v5 to navigate programmatically.
// React Router v6+
import { useNavigate } from "react-router-dom";
function RedirectButton() {
const navigate = useNavigate();
return (
<button onClick={() => navigate("/home")}>Go Home</button>
);
}
// React Router v5
import { useHistory } from "react-router-dom";
function RedirectButton() {
const history = useHistory();
return (
<button onClick={() => history.push("/home")}>Go Home</button>
);
}
How do you get query parameters from React Router?
In React Router v6, use useSearchParams(). In React Router v5, use useLocation() with the browser’s URLSearchParams API.
// React Router v6
import { useSearchParams } from "react-router-dom";
function Page() {
const [searchParams] = useSearchParams();
const user = searchParams.get("user");
return <p>User: {user}</p>;
}
... premium content.
