Top 50 React JS Interview Questions

📚 50 Questions  •  ⏱ ~30 min read  •  Fresher–Intermediate

The most important React interview questions for 2026 — covering hooks, state management, component lifecycle, performance, and React Router. Asked at startups, product companies, and service companies hiring React developers.

Q1What is React? Why is it popular?Easy

React is a JavaScript library (not a full framework) built by Meta for building user interfaces. It renders UI as a tree of components.

Why popular:

  • Component-based — reusable UI building blocks
  • Virtual DOM — efficient updates (only changes what's needed)
  • One-way data flow — predictable, easier to debug
  • Huge ecosystem — React Router, Redux, Next.js, React Native
  • Job market — most in-demand frontend framework in India
Q2What is JSX?Easy

JSX (JavaScript XML) is a syntax extension that lets you write HTML-like code inside JavaScript. It gets compiled to React.createElement() calls by Babel.

// JSX
const element = <h1 className="title">Hello, {name}!</h1>;

// What Babel compiles it to:
const element = React.createElement("h1", { className: "title" }, "Hello, " + name + "!");

JSX rules: Use className not class. Self-close empty tags (<img />). Return one root element (or use a Fragment <>...</>).

Q3What is the Virtual DOM and how does it work?Medium

The Virtual DOM is a lightweight in-memory copy of the real DOM. When state changes:

  1. React creates a new Virtual DOM tree
  2. Compares it with the previous Virtual DOM (diffing)
  3. Calculates the minimum set of changes needed (reconciliation)
  4. Updates only those specific parts of the real DOM

This is faster than directly manipulating the real DOM for every change because DOM operations are expensive.

Q4What is the difference between a functional and class component?Easy
// Functional component (modern — use this)
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Class component (legacy)
class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

Functional components are the modern standard. They support hooks, are simpler, and easier to test. Class components are only seen in older codebases. Interviewers expect you to know both but write functional.

Q5What are props in React?Easy

Props (properties) are how a parent component passes data to a child component. Props are read-only — a child cannot modify its own props.

// Parent
function App() {
  return <Card title="HTML Tutorial" lessons={25} />;
}

// Child
function Card({ title, lessons }) {
  return (
    <div>
      <h2>{title}</h2>
      <p>{lessons} lessons</p>
    </div>
  );
}
Q6What is state in React? How is it different from props?Easy
function Counter() {
  const [count, setCount] = useState(0); // state

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}
  • State — internal, mutable, managed by the component itself
  • Props — external, immutable, passed from parent

When state changes, the component re-renders. When props change (parent re-renders), child also re-renders.

Q7What is one-way data flow in React?Medium

In React, data flows in one direction — from parent to child via props. A child cannot directly modify parent state.

To send data from child to parent, the parent passes a callback function as a prop:

function Parent() {
  const [name, setName] = useState("");
  return <Child onNameChange={setName} />;
}

function Child({ onNameChange }) {
  return (
    <input onChange={e => onNameChange(e.target.value)} />
  );
}

This makes data flow predictable and bugs easier to trace.

Q8What are React keys? Why are they important?Medium

Keys help React identify which items in a list changed, were added, or removed. They must be unique among siblings.

// Wrong — using index as key (bad for reorderable lists)
{items.map((item, index) => <li key={index}>{item}</li>)}

// Correct — use a unique, stable id
{items.map(item => <li key={item.id}>{item.name}</li>)}

Without keys, React may re-render the wrong elements. Using array index as key breaks if the list is reordered or filtered.

Q9What is conditional rendering in React?Easy
// if/else (inside function, before return)
if (isLoggedIn) return <Dashboard />;
return <Login />;

// Ternary (inline)
return <div>{isLoggedIn ? <Dashboard /> : <Login />}</div>;

// Short-circuit (render or nothing)
return <div>{error && <ErrorMessage msg={error} />}</div>;

// Nullish — render nothing
return <div>{isLoading ? <Spinner /> : null}</div>;
Q10What is a React Fragment?Easy

A Fragment lets you return multiple elements from a component without adding an extra DOM node.

// Without Fragment — adds unnecessary <div>
return (
  <div>
    <h1>Title</h1>
    <p>Paragraph</p>
  </div>
);

// With Fragment — no extra DOM element
return (
  <>
    <h1>Title</h1>
    <p>Paragraph</p>
  </>
);

// Or explicit (needed when you need a key prop)
return (
  <React.Fragment key={item.id}>
    <dt>{item.term}</dt>
    <dd>{item.def}</dd>
  </React.Fragment>
);
Q11What is the difference between controlled and uncontrolled components?Medium
// Controlled — React controls the value via state
function ControlledInput() {
  const [value, setValue] = useState("");
  return <input value={value} onChange={e => setValue(e.target.value)} />;
}

// Uncontrolled — DOM controls the value, accessed via ref
function UncontrolledInput() {
  const inputRef = useRef();
  const handleSubmit = () => console.log(inputRef.current.value);
  return <input ref={inputRef} defaultValue="initial" />;
}

Use controlled components for most cases — they give you full control over form data. Uncontrolled is useful for file inputs or when integrating with non-React code.

Q12What is prop drilling? How do you solve it?Medium

Prop drilling is passing props through multiple intermediate components that don't need them, just to get data to a deeply nested component.

// Problem: theme passed through every level
<App theme="dark">
  <Layout theme="dark">
    <Sidebar theme="dark">
      <Button theme="dark" />  {/* only Button needs it */}
    </Sidebar>
  </Layout>
</App>

// Solution 1: React Context
const ThemeContext = createContext("light");
// wrap App with ThemeContext.Provider, use useContext(ThemeContext) in Button

// Solution 2: State management (Redux, Zustand)
Q13What is React Context API?Medium
// 1. Create context
const ThemeContext = createContext("light");

// 2. Provide value (wrap your tree)
function App() {
  const [theme, setTheme] = useState("dark");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <Layout />
    </ThemeContext.Provider>
  );
}

// 3. Consume anywhere in the tree
function Button() {
  const { theme } = useContext(ThemeContext);
  return <button className={theme}>Click</button>;
}

Context avoids prop drilling. Don't overuse it — it causes all consumers to re-render on every change.

Q14What are default props and PropTypes?Easy
import PropTypes from "prop-types";

function Card({ title, count }) {
  return <div>{title}: {count}</div>;
}

// Default props (modern: use default params)
Card.defaultProps = { count: 0 };
// Or: function Card({ title, count = 0 }) { ... }

// PropTypes — runtime type checking
Card.propTypes = {
  title: PropTypes.string.isRequired,
  count: PropTypes.number,
};

In TypeScript projects, use TypeScript interfaces instead of PropTypes.

Q15What is the React component lifecycle?Medium

Three phases:

  • Mounting — component is created and inserted into DOM (constructorrendercomponentDidMount)
  • Updating — state/props change, component re-renders (rendercomponentDidUpdate)
  • Unmounting — component is removed from DOM (componentWillUnmount)

In functional components, all three are handled with useEffect:

useEffect(() => {
  // Mount: run after first render
  fetchData();
  return () => {
    // Unmount: cleanup
    cleanup();
  };
}, []); // [] = run only once
Q16What are React hooks? What are the rules of hooks?Easy

Hooks are functions that let you use React features (state, lifecycle, context) inside functional components.

Built-in hooks: useState, useEffect, useContext, useRef, useMemo, useCallback, useReducer, useId

Rules of hooks:

  • Only call hooks at the top level — not inside loops, conditions, or nested functions
  • Only call hooks from React functions (components or custom hooks)
Q17Explain useState in detail.Easy
const [state, setState] = useState(initialValue);

// Examples
const [count, setCount] = useState(0);
const [user, setUser] = useState(null);
const [items, setItems] = useState([]);

// Update
setCount(5);
setCount(prev => prev + 1); // functional update (safe with stale closures)

// Object state — must spread existing state
const [form, setForm] = useState({ name: "", email: "" });
setForm(prev => ({ ...prev, name: "Priya" }));

State updates are asynchronous — React batches them for performance. Always use the functional form setState(prev => ...) when new state depends on old state.

Q18Explain useEffect and its dependency array.Medium
// Run after every render
useEffect(() => { doSomething(); });

// Run only once (on mount)
useEffect(() => { fetchData(); }, []);

// Run when specific values change
useEffect(() => { fetchUser(userId); }, [userId]);

// Cleanup (runs before next effect + on unmount)
useEffect(() => {
  const timer = setInterval(() => tick(), 1000);
  return () => clearInterval(timer); // cleanup!
}, []);

Common uses: API calls, subscriptions, DOM manipulation, timers, event listeners.

Q19What is useRef? What are its use cases?Medium
// Use case 1: access DOM elements
function TextInput() {
  const inputRef = useRef(null);
  const focus = () => inputRef.current.focus();
  return <><input ref={inputRef} /><button onClick={focus}>Focus</button></>;
}

// Use case 2: store mutable value that doesn't cause re-render
function Timer() {
  const countRef = useRef(0);
  const tick = () => { countRef.current++; }; // no re-render!
}

// Use case 3: store previous state
const prevCount = useRef(count);
useEffect(() => { prevCount.current = count; }, [count]);

Key: ref.current changes do NOT cause a re-render (unlike state).

Q20What is useMemo? When should you use it?Hard
// Without useMemo — recalculates on every render
const sorted = items.sort((a, b) => a - b); // expensive!

// With useMemo — only recalculates when items changes
const sorted = useMemo(() => {
  return [...items].sort((a, b) => a - b);
}, [items]);

Use useMemo when:

  • A computation is expensive (sorting large arrays, complex calculations)
  • A value is used as a dependency in other hooks
  • A referentially stable object needs to be passed as a prop

Don't overuse — premature optimization. Profile first.

Q21What is useCallback? How is it different from useMemo?Hard
// useCallback — memoizes a FUNCTION
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]); // returns same function reference when id doesn't change

// useMemo — memoizes a VALUE
const total = useMemo(() => items.reduce((a, b) => a + b, 0), [items]);

// Memory tip:
// useCallback(fn, deps) === useMemo(() => fn, deps)

Use useCallback when passing callbacks to child components wrapped in React.memo — prevents unnecessary re-renders.

Q22What is useReducer? When do you use it over useState?Hard
const initialState = { count: 0, step: 1 };

function reducer(state, action) {
  switch (action.type) {
    case "increment": return { ...state, count: state.count + state.step };
    case "reset":     return initialState;
    case "setStep":   return { ...state, step: action.payload };
    default: throw new Error("Unknown action");
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
    </>
  );
}

Use useReducer when: state has multiple sub-values, next state depends on previous, or complex update logic (like Redux at a small scale).

Q23What are custom hooks?Medium

Custom hooks are functions that start with use and contain reusable stateful logic using other hooks.

// Custom hook — reusable fetch logic
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(r => r.json())
      .then(d => { setData(d); setLoading(false); })
      .catch(e => { setError(e); setLoading(false); });
  }, [url]);

  return { data, loading, error };
}

// Usage in any component
const { data, loading } = useFetch("/api/users");
Q24What is useContext?Medium
const UserContext = createContext(null);

// Provider (usually in App.jsx)
function App() {
  const [user, setUser] = useState({ name: "Priya" });
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <Router />
    </UserContext.Provider>
  );
}

// Consumer (any deeply nested component)
function Profile() {
  const { user } = useContext(UserContext);
  return <h1>{user.name}</h1>;
}
Q25What is React.memo?Hard

React.memo is a higher-order component that memoizes a component — it only re-renders if its props change.

// Without memo — re-renders every time parent renders
function ExpensiveList({ items }) {
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}

// With memo — only re-renders if items prop changes
const ExpensiveList = React.memo(function ExpensiveList({ items }) {
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});

Combine with useCallback for function props — otherwise the callback creates a new reference every render, defeating memo.

Q26What is useLayoutEffect? How is it different from useEffect?Hard
  • useEffect: fires asynchronously AFTER the browser paints — safe for data fetching, subscriptions
  • useLayoutEffect: fires synchronously AFTER DOM mutations but BEFORE browser paints — use for DOM measurements to prevent visual flicker
// Use useLayoutEffect for DOM measurements
useLayoutEffect(() => {
  const { height } = ref.current.getBoundingClientRect();
  setHeight(height); // set before paint — no flicker
}, []);

Default to useEffect. Only use useLayoutEffect if you see visual flickering from DOM reads/writes.

Q27What is useId?Medium
function FormField({ label }) {
  const id = useId(); // stable unique id across server/client
  return (
    <>
      <label htmlFor={id}>{label}</label>
      <input id={id} />
    </>
  );
}
// Renders: id="r:1", "r:2", etc. — unique per component instance

Added in React 18. Use for connecting form labels to inputs when you need a stable ID that works with server-side rendering.

Q28What is useImperativeHandle?Hard
// Expose specific methods from child to parent
const FancyInput = forwardRef(function FancyInput(props, ref) {
  const inputRef = useRef();

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

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

// Parent
function Form() {
  const inputRef = useRef();
  return (
    <>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus</button>
    </>
  );
}
Q29What causes infinite loops in useEffect?Medium
// ❌ Infinite loop — no dependency array
useEffect(() => {
  setCount(count + 1); // triggers re-render → effect runs again...
});

// ❌ Infinite loop — object/function dependency recreated every render
useEffect(() => {
  fetchData(options);
}, [options]); // options = {} recreated on every render

// ✅ Fix — use functional update
useEffect(() => {
  setCount(prev => prev + 1);
}, []); // only runs once

// ✅ Fix — memoize object dependency
const options = useMemo(() => ({ page: 1 }), []);
Q30What is useTransition and useDeferredValue? (React 18)Hard
// useTransition — mark state update as non-urgent
function Search() {
  const [query, setQuery] = useState("");
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    setQuery(e.target.value); // urgent (input)
    startTransition(() => {
      setResults(filter(e.target.value)); // non-urgent (heavy)
    });
  };
}

// useDeferredValue — defer updating a value
function Results({ query }) {
  const deferredQuery = useDeferredValue(query); // lags behind by one render
  const filtered = useMemo(() => heavyFilter(deferredQuery), [deferredQuery]);
  return <List items={filtered} />;
}

Both are React 18 Concurrent Mode features for keeping the UI responsive during heavy renders.

Q31What is React Router? How do you set it up?Medium
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/user/:id" element={<UserProfile />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}
Q32What are React Router hooks — useNavigate, useParams, useLocation?Medium
import { useNavigate, useParams, useLocation } from "react-router-dom";

function UserProfile() {
  const { id } = useParams();        // /user/42 → id = "42"
  const navigate = useNavigate();    // programmatic navigation
  const location = useLocation();    // current URL info

  return (
    <>
      <p>User ID: {id}</p>
      <p>Current path: {location.pathname}</p>
      <button onClick={() => navigate("/")}>Go Home</button>
      <button onClick={() => navigate(-1)}>Go Back</button>
    </>
  );
}
Q33What is code splitting and lazy loading in React?Hard
import { lazy, Suspense } from "react";

// Lazy load component — only downloads when needed
const Dashboard = lazy(() => import("./Dashboard"));
const Settings  = lazy(() => import("./Settings"));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings"  element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

Code splitting reduces the initial bundle size — users download only the code needed for the current page.

Q34What is an Error Boundary?Hard

Error boundaries catch JavaScript errors in child components and show a fallback UI instead of crashing the whole app. They must be class components.

class ErrorBoundary extends React.Component {
  state = { hasError: false };

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

  componentDidCatch(error, info) {
    logError(error, info); // log to error service
  }

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

// Usage
<ErrorBoundary>
  <RiskyComponent />
</ErrorBoundary>
Q35What is React Suspense?Hard

Suspense lets components "wait" for something (lazy loading, data fetching) and show a fallback while waiting.

// With lazy loading
<Suspense fallback={<Spinner />}>
  <LazyComponent />
</Suspense>

// With React Query / data fetching (React 18+)
<Suspense fallback={<Skeleton />}>
  <UserProfile userId={1} /> {/* suspends while fetching */}
</Suspense>
Q36What is the difference between Redux and Context API?Hard
  • Context API: built-in, good for low-frequency updates (theme, user auth, locale). All consumers re-render on any change.
  • Redux: external library, good for complex, high-frequency state. Selective re-renders with selectors. Built-in devtools for time-travel debugging.

When to use Redux: large app with many components sharing complex state, frequent updates, need for middleware (logging, async). Modern alternative: Zustand — simpler than Redux, smaller bundle.

Q37What is lifting state up?Medium

When two sibling components need to share state, move the state to their nearest common parent and pass it down as props.

// Before: each has own state — can't sync
function TemperatureC() { const [temp, setTemp] = useState(0); ... }
function TemperatureF() { const [temp, setTemp] = useState(32); ... }

// After: state lifted to parent
function Calculator() {
  const [celsius, setCelsius] = useState(0);
  const fahrenheit = celsius * 9/5 + 32;
  return (
    <>
      <TemperatureC value={celsius} onChange={setCelsius} />
      <TemperatureF value={fahrenheit} onChange={f => setCelsius((f-32)*5/9)} />
    </>
  );
}
Q38What are higher-order components (HOC) in React?Hard

A HOC is a function that takes a component and returns a new enhanced component. Used for cross-cutting concerns (auth, logging, data fetching).

// HOC that adds auth protection
function withAuth(WrappedComponent) {
  return function AuthenticatedComponent(props) {
    const { user } = useAuth();
    if (!user) return <Navigate to="/login" />;
    return <WrappedComponent {...props} user={user} />;
  };
}

// Usage
const ProtectedDashboard = withAuth(Dashboard);

HOCs are a pattern from before hooks. Custom hooks are now preferred for most use cases.

Q39What is the render props pattern?Hard
// Component that shares logic via a render prop
function MouseTracker({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  const handleMove = e => setPos({ x: e.clientX, y: e.clientY });
  return <div onMouseMove={handleMove}>{render(pos)}</div>;
}

// Usage
<MouseTracker render={({ x, y }) => <p>X:{x} Y:{y}</p>} />

Like HOCs, render props are a pre-hooks pattern. Custom hooks now solve the same problem more cleanly.

Q40What is forwardRef?Hard
// forwardRef lets a parent pass a ref to a child's DOM element
const FancyInput = forwardRef((props, ref) => {
  return <input ref={ref} className="fancy" {...props} />;
});

// Parent can now access the input DOM directly
function Form() {
  const inputRef = useRef();
  return (
    <>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus</button>
    </>
  );
}
Q41What is React Portals?Hard

Portals render a child into a DOM node outside the parent component's DOM hierarchy — useful for modals, tooltips, and dropdowns.

import { createPortal } from "react-dom";

function Modal({ children, isOpen }) {
  if (!isOpen) return null;
  return createPortal(
    <div className="modal-overlay">{children}</div>,
    document.getElementById("modal-root") // outside #app
  );
}

// HTML: <div id="app"></div> <div id="modal-root"></div>

Events still bubble up through React tree, not the DOM tree.

Q42How does React handle forms?Medium
function RegisterForm() {
  const [form, setForm] = useState({ name: "", email: "", password: "" });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value })); // computed key!
  };

  const handleSubmit = async (e) => {
    e.preventDefault(); // prevent page reload
    await submitForm(form);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="name"     value={form.name}     onChange={handleChange} />
      <input name="email"    value={form.email}    onChange={handleChange} />
      <input name="password" value={form.password} onChange={handleChange} type="password" />
      <button type="submit">Register</button>
    </form>
  );
}
Q43What is reconciliation in React?Hard

Reconciliation is how React updates the DOM efficiently. When state changes, React compares the new Virtual DOM with the previous one (diffing) and updates only what changed.

React's diffing heuristics:

  • Elements of different types → destroy old tree, build new tree
  • Same element type → update changed attributes only
  • Lists → use keys to match old/new items

This is O(n) complexity thanks to the heuristics (vs O(n³) for a naive algorithm).

Q44What is React 18's Concurrent Mode?Hard

Concurrent Mode lets React work on multiple state updates at the same time, interrupt rendering if something more urgent comes in, and resume later. This keeps the UI responsive.

Key features added in React 18:

  • Automatic batching — multiple state updates batched into one render (even in setTimeout, Promises)
  • useTransition — mark updates as low-priority
  • useDeferredValue — defer a value update
  • startTransition — outside of components
// Enable with ReactDOM.createRoot (React 18+)
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
Q45What are React Server Components?Hard

React Server Components (RSC) run on the server, have zero JavaScript sent to the client. They can directly access databases/filesystems. Used heavily in Next.js 13+.

// Server Component (default in Next.js App Router)
async function UserList() {
  const users = await db.query("SELECT * FROM users"); // direct DB access!
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

// Client Component — needs interactivity
"use client";
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c + 1)}>{count}</button>;
}
Q46What is the difference between useEffect and useLayoutEffect — which runs first?Hard

Order of execution after a render:

  1. React renders (runs your component function)
  2. React commits to the DOM
  3. useLayoutEffect fires (synchronous, before paint)
  4. Browser paints the screen
  5. useEffect fires (asynchronous, after paint)

Use useLayoutEffect for measuring DOM elements before the user sees them. Use useEffect for everything else.

Q47What are some React performance optimization techniques?Medium
  • React.memo — prevent re-renders when props haven't changed
  • useMemo — memoize expensive computed values
  • useCallback — stable function references for memoized children
  • Code splitting with React.lazy() — smaller initial bundle
  • Virtualization — render only visible list items (react-window, react-virtual)
  • useTransition — keep UI responsive during heavy updates
  • Avoid unnecessary state — derive values instead of storing them
  • Avoid anonymous functions in JSXonClick={() => fn()} creates new function each render
Q48What is the children prop?Easy
// children is whatever you put between component tags
function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div className="card-body">{children}</div>
    </div>
  );
}

// Usage
<Card title="Welcome">
  <p>This paragraph is the children prop.</p>
  <button>Click me</button>
</Card>
Q49What is batching in React 18?Hard
// React 17 — only batched inside event handlers
setTimeout(() => {
  setCount(c => c + 1); // triggers render
  setFlag(f => !f);     // triggers another render
  // 2 renders
}, 0);

// React 18 — batches everywhere (Automatic Batching)
setTimeout(() => {
  setCount(c => c + 1); // batched
  setFlag(f => !f);     // batched
  // 1 render
}, 0);

Automatic batching means fewer re-renders. Use flushSync() from react-dom if you need to opt out.

Q50What is Next.js and how is it related to React?Medium

Next.js is a React framework built on top of React that adds:

  • File-based routing — no React Router needed
  • Server-side rendering (SSR) — better SEO
  • Static site generation (SSG) — very fast pages
  • API routes — backend endpoints inside the same project
  • Image optimization, font optimization, edge runtime

React is a UI library. Next.js is a full-stack framework using React for the UI layer. Most React jobs in India now expect Next.js knowledge too.