storieasy-logo

React JS Interview Questions for Beginners to Mid-Level Developers

milan

Milan Patel

21 Jul 2025

|

50 min to read

React-interview-questions

ReactJS

FrontendInterview

WebDevelopment

JavaScript

CodingInterview

ReactDeveloper

ReactInterviewQuestions

React is a declarative, component-based JavaScript library developed by Facebook. It allows developers to build dynamic, high-performing user interfaces by using a virtual DOM, reusable components, and a unidirectional data flow. It’s perfect for creating scalable and maintainable front-end applications, especially single-page apps.

1. What is React?

React is an open-source JavaScript library for building user interfaces (UIs), particularly for single-page applications (SPAs), where data changes dynamically without reloading the page.

It helps developers build fast, interactive, and reusable UI components efficiently.

📌 Key Points:

  • Component-based architecture
  • Declarative UI
  • Fast rendering via virtual DOM

💡 When Should You Use React?

  • You’re building interactive UIs like dashboards, eCommerce apps, portfolios
  • You want fast updates when data changes (e.g., real-time chat)
  • You prefer component reusability and clean structure

2. What is JSX?

JSX stands for JavaScript XML. It’s a syntax extension for JavaScript that allows you to write HTML-like code inside JavaScript, which is then transformed into regular React elements using React.createElement().

Think of JSX as writing UI in HTML, but powered by JavaScript underneath.

In-Depth Explanation:

🔹 Why JSX?

Before JSX, we had to manually call React.createElement() to build UI:

1React.createElement('h1', null, 'Hello World');

With JSX, we can write this instead:

1<h1>Hello World</h1>

✅ Easier to read
✅ Looks like HTML
✅ Still 100% JavaScript

3. What are Components in React?

A component in React is a reusable, independent, and isolated block of code that represents part of the user interface (UI).

Think of components like LEGO blocks 🧱— you build a complete UI by assembling these blocks.

Functional Component (Modern & Preferred)

1function Welcome(props) {
2  return <h1>Hello, {props.name}!</h1>;
3}

With Hooks Example:

1function Counter() {
2  const [count, setCount] = React.useState(0);
3  
4  return (
5    <div>
6      <p>Count: {count}</p>
7      <button onClick={() => setCount(count + 1)}>+1</button>
8    </div>
9  );
10}
11

Class Component (Before Hooks):

1class Welcome extends React.Component {
2  render() {
3    return <h1>Hello, {this.props.name}!</h1>;
4  }
5}
6

Why Use Components?

  • Reusability: Define once, use anywhere.
  • Separation of concerns: Logic and UI are neatly organized.
  • Composition: Build complex UIs by nesting smaller components.

Component Structure Example

1function App() {
2  return (
3    <div>
4      <Header />
5      <Profile name="Milan" />
6      <Footer />
7    </div>
8  );
9}
10
11function Header() {
12  return <h1>My App</h1>;
13}
14
15function Profile(props) {
16  return <p>Welcome, {props.name}</p>;
17}
18
19function Footer() {
20  return <small>&copy; 2025</small>;
21}
22

4. What are Props in React?

Props (short for properties) are read-only inputs passed from parent to child components in React. They allow components to be dynamic and reusable by supplying external data.

Example of Using Props:

1// Parent Component
2function App() {
3  return <Greeting name="Milan" age={25} />;
4}
5
6// Child Component
7function Greeting(props) {
8  return (
9    <div>
10      <h2>Hello, {props.name} 👋</h2>
11      <p>You are {props.age} years old.</p>
12    </div>
13  );
14}
15

Destructuring Props (Cleaner Syntax)

1function Greeting({ name, age }) {
2  return (
3    <div>
4      <h2>Hello, {name} </h2>
5      <p>You are {age} years old.</p>
6    </div>
7  );
8}
9

5. What is State in React?

State is a built-in object in React that holds data or information about the component that may change over time. It is mutable (unlike props) and is used to control the behavior and rendering of the component dynamically.

🔹 Why Use State?

  • To store and manage dynamic data (e.g., user input, form values, counters, API data).
  • To trigger UI updates when data changes.
  • To create interactive components.
1import { useState } from 'react';
2
3function Counter() {
4  const [count, setCount] = useState(0); // [stateValue, updaterFunction]
5
6  return (
7    <div>
8      <h2>Count: {count}</h2>
9      <button onClick={() => setCount(count + 1)}>Increment</button>
10    </div>
11  );
12}
13

💡 What’s happening here?

  • count is the state value
  • setCount is the function to update the state
  • useState(0) initializes the state to 0
  • Clicking the button updates the state, causing a re-render

Multiple States Example:

1function Form() {
2  const [name, setName] = useState('');
3  const [email, setEmail] = useState('');
4
5  return (
6    <form>
7      <input placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} />
8      <input placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} />
9    </form>
10  );
11}
12

6. Difference Between Props and State in React

FeaturePropsState
DefinitionRead-only data passed from parent to childInternal data managed within the component
MutabilityImmutable – cannot be changed by the component itself Mutable – can be updated with setState / useState
Managed ByParent component Component itself
UsageConfigure child components or display dataTrack data that changes over time (user input, UI state)
UpdatesDoes not trigger by itself Updating triggers a re-render
AccessPassed in as parameters (props.title) Accessed via this.state (class) or [state, setState]
PurposeCommunicate between components Control the internal behavior of a component

7. What is useState in React?

useState is a React Hook that lets you add and manage local state in a functional component.

In the past, only class components could have state, but with React 16.8 and onwards, Hooks like useState allowed functional components to become fully stateful and powerful.

syntex:

1const [stateVariable, setStateFunction] = useState(initialValue);
  • stateVariable: The current state value.
  • setStateFunction: A function used to update the state.
  • initialValue: The value you want the state to start with.

8. What is useEffect in React?

useEffect is another core Hook that lets you perform side effects in a functional component. Think of things like:

  • Fetching data
  • Subscribing to events
  • Manually updating the DOM
  • Working with timers or external libraries

It replaces lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount used in class components.

🔧 Example 1: Run Once After Initial Render (Like componentDidMount)
1useEffect(() => {
2  console.log("📦 Component mounted");
3}, []);
4
The empty dependency array [] means: run this effect only once when the component mounts.

🔧 Example 2: Run When a Value Changes
1useEffect(() => {
2  console.log(`🔁 Count changed to: ${count}`);
3}, [count]);

9. What is the Virtual DOM?

The Virtual DOM (VDOM) is a lightweight JavaScript representation of the real DOM (Document Object Model).
It’s a concept implemented by libraries like React to optimize UI updates and make rendering faster and more efficient.

🔍 Real DOM vs Virtual DOM
AspectReal DOM Virtual DOM
SpeedSlow, direct manipulation Fast, abstract layer
Update Cost Expensive (repaints, reflows) Cheap (only changes are applied)
Rerender Logic Directly updates browser DOM Calculates diff, then updates real DOM
MemoryLightweightEven more lightweight
How Virtual DOM Works (Step-by-step):
  1. Initial Render:
    • When you load a React app, React creates a Virtual DOM tree from your components.

2. State/Props Change:

  • Any interaction or data change (like a button click, form input, etc.) causes state or props to update.

3. VDOM Re-render:

  • React creates a new Virtual DOM tree reflecting the updated UI.

4. Diffing Algorithm:

  • React compares the old VDOM tree with the new one using an efficient algorithm (reconciliation).
  • Only the differences (diff) are calculated — not the entire tree.

6. Efficient Real DOM Update:

  • Based on the diff, React performs a batch update on the actual DOM to match the new UI.
  • This process is faster than updating the entire real DOM directly.

10. What is Conditional Rendering in React?

Conditional rendering in React means dynamically displaying UI elements based on certain conditions — just like you would use if, else, or switch in regular JavaScript.
It allows you to show, hide, or change components or content depending on the current state, props, or logic.

🔧 Common Methods of Conditional Rendering in React:

Example:

1. Using if/else statements:

1if (isLoggedIn) {
2  return <h2>Welcome, Milan!</h2>;
3} else {
4  return <button>Login</button>;
5}
2. Using Ternary Operator (condition ? true : false):
1return (
2  <div>
3    {isLoggedIn ? <p>Logout</p> : <p>Please login</p>}
4  </div>
5);

11. What is the Context API in React?

The Context API in React is a state management tool that allows you to share data globally across your component tree without passing props manually at every level.

It’s React’s built-in alternative to tools like Redux or Zustand for simpler use cases.

Problem Context Solves:
🔁 Props Drilling Issue:

In a deeply nested component structure, if you want to pass data from parent to child, you’d usually do this:

1<Parent>
2  <Child1>
3    <Child2>
4      <Child3>
5        <TargetComponent data={user} />
6      </Child3>
7    </Child2>
8  </Child1>
9</Parent>
10

This is called "props drilling" – passing data through multiple components that don't even need it, just to get it to one that does.

🎯 Context API Solves This!

It allows you to create global data that can be accessed from any child component, no matter how deep in the component tree.

🔧 How Context API Works:
✅ 3 Key Steps:
  1. Create Context
1import React from 'react';
2
3export const ThemeContext = React.createContext();
4

2. Provide Context

1import React, { useState } from 'react';
2import { ThemeContext } from './ThemeContext';
3
4function App() {
5  const [theme, setTheme] = useState("light");
6
7  return (
8    <ThemeContext.Provider value={{ theme, setTheme }}>
9      <Layout />
10    </ThemeContext.Provider>
11  );
12}

3. Consume Context (Any child component)

1import React, { useContext } from 'react';
2import { ThemeContext } from './ThemeContext';
3
4function Header() {
5  const { theme, setTheme } = useContext(ThemeContext);
6
7  return (
8    <div className={theme === "dark" ? "dark-mode" : "light-mode"}>
9      <h2>Current Theme: {theme}</h2>
10      <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
11        Toggle Theme
12      </button>
13    </div>
14  );
15}

12. What are Controlled and Uncontrolled Components in React?

In React, form elements like <input>, <textarea>, and <select> can be handled in two ways:

Controlled Components:

A controlled component is a form input whose value is controlled by React state.
React is the single source of truth.

Example:

1import { useState } from "react";
2
3function ControlledForm() {
4  const [name, setName] = useState("");
5
6  const handleChange = (e) => {
7    setName(e.target.value);
8  };
9
10  return (
11    <input type="text" value={name} onChange={handleChange} />
12  );
13}

📌 Key Points:

  • The <input> value comes from useState.
  • The input is updated only via setName().
  • React fully controls the input's value.
Uncontrolled Components

An uncontrolled component stores its own internal state in the DOM, not in React.
You use ref to access the current value.

Example:

1import { useRef } from "react";
2
3function UncontrolledForm() {
4  const nameRef = useRef();
5
6  const handleSubmit = () => {
7    alert(`Name: ${nameRef.current.value}`);
8  };
9
10  return (
11    <>
12      <input type="text" ref={nameRef} />
13      <button onClick={handleSubmit}>Submit</button>
14    </>
15  );
16}

📌 Key Points:

  • The input's value is not managed by React state.
  • You use ref to read the value directly from the DOM.
  • Less React overhead, but less control.
🔍 When to Use Which?
  • Controlled:
    • Dynamic validation
    • Live feedback
    • Interdependent inputs
    • Clean debugging and testing
  • 🟡 Uncontrolled:
    • Quick form setup
    • Third-party libraries
    • Non-critical forms
    • Performance-sensitive inputs

13. What is useRef in React?

useRef is a React Hook that allows you to create a mutable reference which persists across re-renders and does not trigger a re-render when updated.

It can be used for:

  • Accessing DOM elements directly
  • Holding mutable values
  • Storing previous state values

Syntax:

1const myRef = useRef(initialValue);

Accessing DOM Elements:

1import { useRef } from 'react';
2
3function FocusInput() {
4  const inputRef = useRef();
5
6  const handleFocus = () => {
7    inputRef.current.focus(); // Directly focuses the input
8  };
9
10  return (
11    <>
12      <input ref={inputRef} type="text" placeholder="Type here..." />
13      <button onClick={handleFocus}>Focus Input</button>
14    </>
15  );
16}
✅ What’s happening?
  • inputRef stores a reference to the DOM node
  • You can use .current to access the real input element and call .focus() on it

Store Mutable Values (without causing re-renders):

1import { useRef, useState } from 'react';
2
3function TimerCounter() {
4  const countRef = useRef(0);
5  const [render, setRender] = useState(false);
6
7  const increaseCount = () => {
8    countRef.current += 1;
9    console.log("Count (ref):", countRef.current);
10  };
11
12  return (
13    <>
14      <p>Click the button to increase count (not re-rendered)</p>
15      <button onClick={increaseCount}>Increase</button>
16      <button onClick={() => setRender(!render)}>Force Re-render</button>
17    </>
18  );
19}
20
✅ Key Insight:
  • useRef holds values without triggering re-renders
  • Perfect for counters, timers, intervals, etc., that don’t need UI updates

14. What is React.memo in React?

React.memo is a higher-order component (HOC) that memoizes a functional component — meaning it prevents unnecessary re-renders if the component's props haven’t changed.

Syntax:

1const MemoizedComponent = React.memo(Component);

Example:

1const MemoizedComponent = React.memo(Component);
2
3//Or with arrow function:
4
5const MyComponent = React.memo((props) => {
6  return <div>{props.value}</div>;
7});
Why Use React.memo?

React components re-render every time their parent re-renders, even if the props haven't changed.
React.memo skips rendering if props are the same, which boosts performance in certain cases.

15. What is useCallback and Why Use It in React?

useCallback is a React Hook that memoizes a function, meaning it returns the same function reference unless its dependencies change.

It's used to optimize performance and prevent unnecessary re-renders, especially when passing callback functions to child components.

Syntax:

1const memoizedCallback = useCallback(() => {
2  // your function logic here
3}, [dependencies]);
Why Is useCallback Needed?

In React:

  • Functions are re-created on every render, even if logic stays the same.
  • If you're passing functions as props to memoized components (like React.memo), those child components will re-render because the function reference changes.

useCallback prevents this problem by giving you a stable reference to the same function unless dependencies change.

With useCallback:

1const Parent = () => {
2  const [count, setCount] = useState(0);
3
4  const handleClick = useCallback(() => {
5    console.log("Clicked");
6  }, []); // No dependency = stable reference
7
8  return (
9    <>
10      <Child onClick={handleClick} />
11      <button onClick={() => setCount(count + 1)}>Increment</button>
12    </>
13  );
14};

Now, Child won’t re-render on every parent update because handleClick has a stable identity thanks to useCallback.

16. What is Lifting State Up in React?

Lifting state up is a technique in React used to share state between two or more components that are siblings (i.e., they are at the same level in the component tree) by moving the shared state to their closest common ancestor.

Why It's Needed

When two or more child components need to access or modify the same state, managing that state within each individual component can lead to inconsistency. Instead, React recommends lifting the state up to the parent component that renders those children. This parent can then pass down the shared state and any state-updating functions via props.

Real-World Example

Let’s say you have two components:

  • <TemperatureInput /> — one for Celsius
  • <TemperatureInput /> — another for Fahrenheit
    Both need to keep their values in sync.

If each manages its own state, syncing them becomes messy. Instead, you lift the temperature state up to a common parent component.

Example:

1// Parent Component
2function TemperatureConverter() {
3  const [temperature, setTemperature] = useState('');
4
5  return (
6    <>
7      <TemperatureInput
8        scale="Celsius"
9        temperature={temperature}
10        onTemperatureChange={setTemperature}
11      />
12      <TemperatureInput
13        scale="Fahrenheit"
14        temperature={(temperature * 9) / 5 + 32}
15        onTemperatureChange={(value) =>
16          setTemperature(((value - 32) * 5) / 9)
17        }
18      />
19    </>
20  );
21}
22
23// Child Component
24function TemperatureInput({ scale, temperature, onTemperatureChange }) {
25  return (
26    <div>
27      <label>{scale}:</label>
28      <input
29        type="number"
30        value={temperature}
31        onChange={(e) => onTemperatureChange(Number(e.target.value))}
32      />
33    </div>
34  );
35}

What’s Happening

  • The state temperature is in the parent TemperatureConverter.
  • The child <TemperatureInput /> components receive both the temperature and update function via props.
  • Changes made in either child component will reflect in the other, because they both depend on the same source of truth.

✅ Benefits

  • Single source of truth for shared state.
  • Easier to synchronize data between components.
  • Promotes reusability and separation of concerns.

17. What is Prop Drilling in React?

Prop Drilling is when you pass data from a parent component to a deeply nested child component through multiple intermediate components, even if those intermediate components don’t need the data themselves.

🧩 Code Example: Before Optimization

1// App.jsx
2import Parent from './Parent';
3
4export default function App() {
5  const user = { name: "Milan", role: "Admin" };
6  return <Parent user={user} />;
7}
1// Parent.jsx
2import Child from './Child';
3
4export default function Parent({ user }) {
5  return <Child user={user} />;
6}
1// Child.jsx
2import GrandChild from './GrandChild';
3
4export default function Child({ user }) {
5  return <GrandChild user={user} />;
6}
1// GrandChild.jsx
2export default function GrandChild({ user }) {
3  return <h3>Welcome, {user.name}!</h3>;
4}
😩 Problem Here:

We had to pass user through App → Parent → Child → GrandChild just so the last one could use it.
The middle components don’t even care about user, yet they must forward it. That’s prop drilling.

🛠️ Why Prop Drilling is a Problem:
  • Makes code harder to read and maintain.
  • Every component in the chain becomes tightly coupled.
  • When your app grows, it leads to repetitive and bloated code.
✅ Solution: Use Context API

Instead of drilling props, we can store the data in a context and allow any component to access it directly — no need to pass through each layer.

1// UserContext.js
2import { createContext } from "react";
3export const UserContext = createContext(null);
1// App.jsx
2import { UserContext } from "./UserContext";
3import Parent from "./Parent";
4
5export default function App() {
6  const user = { name: "Milan", role: "Admin" };
7
8  return (
9    <UserContext.Provider value={user}>
10      <Parent />
11    </UserContext.Provider>
12  );
13}
1// GrandChild.jsx
2import { useContext } from "react";
3import { UserContext } from "./UserContext";
4
5export default function GrandChild() {
6  const user = useContext(UserContext);
7  return <h3>Welcome, {user.name}!</h3>; // Directly accessed!
8}

🚀 Benefits of Avoiding Prop Drilling

  • Cleaner and more modular code
  • Reusable components
  • Better scalability for large apps

18. How to Optimize Performance in React

Avoid Unnecessary Re-renders

🔹 Use React.memo() for components:

1const MyComponent = React.memo(function MyComponent({ name }) {
2  return <p>Hello, {name}</p>;
3});

🔹 Use useCallback() to memoize functions:

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

🔹 Use useMemo() to cache expensive calculations:

1const expensiveValue = useMemo(() => computeHeavyValue(data), [data]);
Code Splitting with Dynamic Imports

Only load what's needed:

1const LazyComponent = React.lazy(() => import('./BigComponent'));
2
3<Suspense fallback={<Loading />}>
4  <LazyComponent />
5</Suspense>

🔧 Tools:

  • React.lazy
  • @loadable/component for better SSR
Image Optimization

Tools:

  • next/image (in Next.js)
  • react-image for lazy loading
  • CDN like Cloudinary, Imgix, or ImageKit
Tips:
  • Compress images before upload
  • Use webp or avif format
  • Lazy load below-the-fold images
  • Use responsive sizes (srcSet, sizes)
1<img
2  src="/img/banner.webp"
3  loading="lazy"
4  width="100%"
5  height="auto"
6  alt="Optimized"
7/>
Pagination or Infinite Scroll

Don’t load everything at once.

1const [page, setPage] = useState(1);
2useEffect(() => {
3  fetch(`/api/posts?page=${page}`);
4}, [page]);
Virtualize Long Lists
1import { FixedSizeList as List } from 'react-window';
2
3<List height={400} itemCount={1000} itemSize={35} width={300}>
4  {({ index, style }) => <div style={style}>Row {index}</div>}
5</List>
Use Context Wisely

Context updates re-render all consuming components. Avoid putting frequently-changing values in Context.

Solution: Separate global state with tools like:

  • Zustand
  • Jotai
  • Redux Toolkit
  • Recoil
Debounce or Throttle Expensive Events
1const debouncedSearch = useMemo(() => debounce(handleSearch, 300), []);

Preload Important Resources

In index.html or Head tag:

1<link rel="preload" href="/fonts/font.woff2" as="font" type="font/woff2" crossorigin="anonymous" />
Avoid Anonymous Functions in JSX
1// ❌ Slow
2<button onClick={() => handleClick()} />
3
4// ✅ Fast
5const onClick = useCallback(() => handleClick(), []);
6<button onClick={onClick} />
Use Production Build
1npm run build

Newsletter

Subscribe to our newsletter and get our latest updates.

Share with your friends: