Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools
React JS

Top 50 React JS Interview Questions

Curated questions covering hooks, state, props, context, virtual DOM, React Router, performance optimization, Redux, and modern React patterns.

01

What is React and what are its key features?

React is a JavaScript library by Meta for building user interfaces. Key features: component-based architecture, virtual DOM for efficient updates, unidirectional data flow, JSX syntax, hooks for state and side effects, and a rich ecosystem (React Router, Redux, React Query).

02

What is the Virtual DOM and how does it work?

The Virtual DOM is a lightweight JavaScript representation of the real DOM. When state changes, React creates a new Virtual DOM tree, diffs it against the previous one (reconciliation), and applies only the minimal set of changes to the real DOM. This batching makes updates efficient.

03

What is the difference between props and state?

  • props - read-only data passed from parent to child. A component cannot modify its own props.
  • state - mutable data managed within a component using useState. Changes to state trigger a re-render.
  • Both changes cause re-renders, but only state is owned and controlled by the component itself.
04

What are React Hooks and why were they introduced?

Hooks are functions that let functional components use state and lifecycle features. Introduced in React 16.8 to replace class components. Benefits: reuse stateful logic without HOCs/render props, simpler code, no this keyword confusion.

05

What is useState and how does it work?

useState returns a state value and a setter function. The setter triggers a re-render with the new value. State updates are asynchronous and batched.

Example
const [count, setCount] = useState(0);\n\n// Direct value\nsetCount(5);\n\n// Functional update (use when new state depends on old)\nsetCount(prev => prev + 1);
06

What is useEffect and when does it run?

useEffect runs side effects after render. The dependency array controls when it re-runs.

  • No array - runs after every render.
  • Empty array [] - runs once after mount (componentDidMount).
  • [dep1, dep2] - runs when any dependency changes.
  • Return a cleanup function to run on unmount or before next effect.
Example
useEffect(() => {\n  const sub = subscribe(userId);\n  return () => sub.unsubscribe(); // cleanup\n}, [userId]);
07

What is useContext and when should you use it?

useContext reads a value from a React Context without prop drilling. Best for global data like theme, locale, or auth state. Not a replacement for state management in large apps — context re-renders all consumers on every change.

Example
const ThemeContext = createContext("light");\n\nfunction App() {\n  return (\n    <ThemeContext.Provider value="dark">\n      <Child />\n    </ThemeContext.Provider>\n  );\n}\n\nfunction Child() {\n  const theme = useContext(ThemeContext); // "dark"\n}
08

What is useRef and what are its use cases?

useRef returns a mutable ref object whose .current property persists across renders without causing re-renders.

  • Accessing DOM elements directly (focus, scroll, measure).
  • Storing mutable values that should not trigger re-renders (timers, previous values).
  • Keeping a stable reference to a callback or value.
Example
const inputRef = useRef(null);\n\nfunction focusInput() {\n  inputRef.current.focus();\n}\n\nreturn <input ref={inputRef} />;
09

What is useMemo and when should you use it?

useMemo memoizes the result of an expensive computation, recomputing only when dependencies change. Use it when a calculation is genuinely expensive and runs on every render.

Example
const sortedList = useMemo(() => {\n  return [...items].sort((a, b) => a.name.localeCompare(b.name));\n}, [items]); // only re-sorts when items changes
10

What is useCallback and how does it differ from useMemo?

  • useMemo - memoizes a computed value. Returns the result of the function.
  • useCallback - memoizes a function reference. Returns the function itself.
  • Use useCallback when passing callbacks to child components wrapped in React.memo to prevent unnecessary re-renders.
Example
const handleClick = useCallback(() => {\n  doSomething(id);\n}, [id]); // stable reference unless id changes
11

What is the difference between useEffect and useLayoutEffect?

  • useEffect - runs asynchronously after the browser has painted. Does not block the browser. Use for most side effects.
  • useLayoutEffect - runs synchronously after DOM mutations but before the browser paints. Use for DOM measurements and synchronous visual updates to avoid flicker.
12

What is React.memo and when should you use it?

React.memo is a HOC that memoizes a functional component, preventing re-renders if props have not changed (shallow comparison). Use it for pure components that render often with the same props.

Example
const UserCard = React.memo(({ user }) => {\n  return <div>{user.name}</div>;\n});\n\n// Custom comparison\nconst UserCard = React.memo(({ user }) => (\n  <div>{user.name}</div>\n), (prevProps, nextProps) => prevProps.user.id === nextProps.user.id);
13

What is the difference between controlled and uncontrolled components?

  • Controlled - form element value is controlled by React state. Every change updates state via onChange. Single source of truth.
  • Uncontrolled - form element manages its own state in the DOM. Access value via ref. Less React code but harder to validate.
Example
// Controlled\nconst [value, setValue] = useState("");\n<input value={value} onChange={e => setValue(e.target.value)} />\n\n// Uncontrolled\nconst ref = useRef();\n<input ref={ref} defaultValue="initial" />
14

What is the React reconciliation algorithm?

Reconciliation is how React updates the DOM efficiently. React compares the new Virtual DOM tree with the previous one using a diffing algorithm. Key rules: elements of different types produce different trees; use key prop for lists to help React identify which items changed, were added, or removed.

15

What is the key prop and why is it important?

The key prop helps React identify which list items have changed, been added, or removed. Keys must be unique among siblings. Using index as key causes bugs when the list is reordered. Use stable unique IDs.

Example
// Bad - index as key causes issues on reorder\n{items.map((item, i) => <Item key={i} {...item} />)}\n\n// Good - stable unique ID\n{items.map(item => <Item key={item.id} {...item} />)}
16

What is useReducer and when should you use it over useState?

useReducer manages complex state logic with a reducer function (like Redux). Prefer it over useState when: state has multiple sub-values, next state depends on previous state in complex ways, or state transitions follow clear action patterns.

Example
const reducer = (state, action) => {\n  switch (action.type) {\n    case "increment": return { count: state.count + 1 };\n    case "reset": return { count: 0 };\n    default: return state;\n  }\n};\n\nconst [state, dispatch] = useReducer(reducer, { count: 0 });\ndispatch({ type: "increment" });
17

What is the Context API and what are its limitations?

Context provides a way to pass data through the component tree without prop drilling. Limitations: every consumer re-renders when context value changes (even if they only use part of it); not optimized for high-frequency updates; for complex state, use Zustand, Redux, or Jotai instead.

18

What is React Router and how do you set up routes?

React Router enables client-side navigation. v6 uses Routes and Route components with element prop.

Example
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";\n\nfunction App() {\n  return (\n    <BrowserRouter>\n      <Routes>\n        <Route path="/" element={<Home />} />\n        <Route path="/users/:id" element={<User />} />\n        <Route path="*" element={<NotFound />} />\n      </Routes>\n    </BrowserRouter>\n  );\n}
19

What is code splitting and lazy loading in React?

Code splitting splits the bundle into smaller chunks loaded on demand. React.lazy() and Suspense enable component-level lazy loading.

Example
const Dashboard = React.lazy(() => import("./Dashboard"));\n\nfunction App() {\n  return (\n    <Suspense fallback={<Spinner />}>\n      <Dashboard />\n    </Suspense>\n  );\n}
20

What is the difference between React.lazy and dynamic import?

  • dynamic import() - a JavaScript feature that returns a Promise resolving to the module. Works anywhere.
  • React.lazy() - wraps a dynamic import for use with React components. Must be used with Suspense. Only works for default exports.
21

What is Redux and when should you use it?

Redux is a predictable state management library. Use it when: multiple components need the same state, state changes are complex, you need time-travel debugging, or the app is large. For simpler cases, Context + useReducer or Zustand are lighter alternatives.

22

What is the difference between Redux Toolkit and classic Redux?

Redux Toolkit (RTK) is the official recommended way to write Redux. It eliminates boilerplate with createSlice (combines actions + reducer), createAsyncThunk (async actions), and configureStore (sets up middleware automatically).

Example
const counterSlice = createSlice({\n  name: "counter",\n  initialState: { value: 0 },\n  reducers: {\n    increment: state => { state.value += 1; }, // Immer allows mutation\n    decrement: state => { state.value -= 1; }\n  }\n});\nexport const { increment, decrement } = counterSlice.actions;
23

What is the difference between useSelector and useDispatch?

  • useSelector - reads state from the Redux store. Re-renders the component when the selected state changes.
  • useDispatch - returns the dispatch function to send actions to the store.
Example
const count = useSelector(state => state.counter.value);\nconst dispatch = useDispatch();\n\nreturn <button onClick={() => dispatch(increment())}>+{count}</button>;
24

What are Higher-Order Components (HOCs)?

A HOC is a function that takes a component and returns a new enhanced component. Used for cross-cutting concerns like authentication, logging, and data fetching. Largely replaced by hooks in modern React.

Example
function withAuth(Component) {\n  return function AuthenticatedComponent(props) {\n    const { isLoggedIn } = useAuth();\n    if (!isLoggedIn) return <Redirect to="/login" />;\n    return <Component {...props} />;\n  };\n}
25

What are render props?

Render props is a pattern where a component accepts a function as a prop and calls it to render UI. Enables sharing stateful logic between components. Largely replaced by hooks.

Example
function MouseTracker({ render }) {\n  const [pos, setPos] = useState({ x: 0, y: 0 });\n  return (\n    <div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>\n      {render(pos)}\n    </div>\n  );\n}\n\n<MouseTracker render={({ x, y }) => <p>{x}, {y}</p>} />
26

What is the difference between useImperativeHandle and forwardRef?

forwardRef passes a ref from a parent to a child DOM element or component. useImperativeHandle customizes what the parent sees when it accesses the ref — exposing only specific methods instead of the full DOM node.

Example
const Input = forwardRef((props, ref) => {\n  useImperativeHandle(ref, () => ({\n    focus: () => inputRef.current.focus(),\n    clear: () => inputRef.current.value = ""\n  }));\n  const inputRef = useRef();\n  return <input ref={inputRef} {...props} />;\n});
27

What is React Suspense?

Suspense lets components wait for something (lazy-loaded component, data fetch) before rendering. Shows a fallback UI while waiting. Works with React.lazy() and data-fetching libraries like React Query and Relay.

Example
<Suspense fallback={<LoadingSpinner />}>\n  <LazyComponent />\n  <DataComponent /> {/* with use() hook in React 19 */}\n</Suspense>
28

What is the difference between React 18 concurrent features and legacy rendering?

  • Legacy (ReactDOM.render) - synchronous rendering; long renders block the browser.
  • Concurrent (createRoot) - React can pause, resume, and prioritize renders. Enables Suspense, useTransition, useDeferredValue, and automatic batching.
Example
// React 18 concurrent mode\nimport { createRoot } from "react-dom/client";\nconst root = createRoot(document.getElementById("root"));\nroot.render(<App />);
29

What is useTransition?

useTransition marks a state update as non-urgent, allowing React to keep the UI responsive while the update is processed. Returns isPending (boolean) and startTransition (function).

Example
const [isPending, startTransition] = useTransition();\n\nfunction handleSearch(value) {\n  setInputValue(value); // urgent - update input immediately\n  startTransition(() => {\n    setSearchResults(filterItems(value)); // non-urgent\n  });\n}
30

What is useDeferredValue?

useDeferredValue defers updating a value until the browser is idle, similar to useTransition but for values you do not control (e.g., from props). Useful for deferring expensive re-renders.

Example
const deferredQuery = useDeferredValue(query);\n\n// ExpensiveList only re-renders when browser is idle\nreturn (\n  <>\n    <input value={query} onChange={e => setQuery(e.target.value)} />\n    <ExpensiveList query={deferredQuery} />\n  </>\n);
31

What is automatic batching in React 18?

In React 17, state updates inside setTimeout, Promises, and native event handlers were not batched. React 18 automatically batches all state updates regardless of where they occur, reducing unnecessary re-renders.

Example
// React 18: both setCount and setFlag trigger only ONE re-render\nsetTimeout(() => {\n  setCount(c => c + 1);\n  setFlag(f => !f);\n}, 1000);
32

What is the difference between React Query and Redux for server state?

  • Redux - general-purpose client state management. Managing server state in Redux requires manual loading/error/caching logic.
  • React Query (TanStack Query) - purpose-built for server state: automatic caching, background refetching, stale-while-revalidate, pagination, and optimistic updates. Much less boilerplate for API data.
Example
const { data, isLoading, error } = useQuery({\n  queryKey: ["users"],\n  queryFn: () => fetch("/api/users").then(r => r.json())\n});
33

What is the difference between client-side and server-side rendering in React?

  • CSR (Create React App) - HTML is minimal; JavaScript renders everything in the browser. Slower initial load, fast subsequent navigation.
  • SSR (Next.js) - HTML is rendered on the server per request. Faster initial load, better SEO.
  • SSG (Static Site Generation) - HTML generated at build time. Fastest, best for content that does not change often.
34

What are React Server Components?

React Server Components (RSC) run on the server and never ship their JavaScript to the client. They can directly access databases and file systems. They cannot use hooks or browser APIs. Client Components use "use client" directive. RSC is the foundation of Next.js App Router.

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

What is the useId hook?

useId generates a unique, stable ID that is consistent between server and client renders. Use it for accessibility attributes (htmlFor, aria-describedby) to avoid hydration mismatches.

Example
function FormField({ label }) {\n  const id = useId();\n  return (\n    <>\n      <label htmlFor={id}>{label}</label>\n      <input id={id} />\n    </>\n  );\n}
36

What is the difference between React.cloneElement and React.createElement?

  • React.createElement(type, props, children) - creates a new React element from scratch. Used by JSX under the hood.
  • React.cloneElement(element, props, children) - clones an existing element and merges new props. Used in HOCs and compound components to inject props into children.
37

What is prop drilling and how do you avoid it?

Prop drilling is passing props through multiple intermediate components that do not use them. Solutions: Context API (for global data), component composition (pass components as props), state management libraries (Redux, Zustand), or custom hooks.

38

What is the difference between React.Fragment and empty tags?

Both group elements without adding a DOM node. React.Fragment supports the key prop (required in lists). Empty tags (<>) are shorthand and do not support key.

Example
// Supports key prop - use in lists\n{items.map(item => (\n  <React.Fragment key={item.id}>\n    <dt>{item.term}</dt>\n    <dd>{item.desc}</dd>\n  </React.Fragment>\n))}
39

What is the difference between defaultProps and default parameter values?

defaultProps is the legacy way to set default prop values for class and function components. Modern React uses ES6 default parameter values in function signatures, which is simpler and works with TypeScript better. defaultProps is deprecated for function components.

Example
// Modern approach (preferred)\nfunction Button({ label = "Click me", disabled = false }) {\n  return <button disabled={disabled}>{label}</button>;\n}
40

What is Zustand and how does it compare to Redux?

Zustand is a lightweight state management library. Compared to Redux: no boilerplate (no actions/reducers/selectors), no Provider needed, simpler API, smaller bundle. Best for small-to-medium apps. Redux Toolkit is better for large apps needing strict patterns and devtools.

Example
const useStore = create((set) => ({\n  count: 0,\n  increment: () => set(state => ({ count: state.count + 1 })),\n  reset: () => set({ count: 0 })\n}));\n\nconst { count, increment } = useStore();
41

What is the difference between useEffect cleanup and componentWillUnmount?

useEffect cleanup function runs both on unmount AND before the next effect runs (when dependencies change). componentWillUnmount only runs on unmount. This means useEffect cleanup is more powerful — it prevents stale subscriptions on every dependency change.

Example
useEffect(() => {\n  const ws = new WebSocket(url);\n  ws.onmessage = handleMessage;\n  return () => ws.close(); // runs on unmount AND when url changes\n}, [url]);
42

What is the React use() hook?

use() (React 19) is a new hook that reads the value of a Promise or Context. Unlike other hooks, it can be called conditionally. It integrates with Suspense — the component suspends while the Promise is pending.

Example
// React 19\nfunction UserProfile({ userPromise }) {\n  const user = use(userPromise); // suspends until resolved\n  return <h1>{user.name}</h1>;\n}
43

What is the difference between React.StrictMode and production mode?

StrictMode is a development tool that helps find bugs by: double-invoking render functions and effects to detect side effects, warning about deprecated APIs, and detecting unexpected side effects. It has no effect in production builds.

44

What is the difference between optimistic and pessimistic UI updates?

  • Pessimistic - wait for server confirmation before updating the UI. Safer but feels slow.
  • Optimistic - update the UI immediately, then sync with the server. Roll back on error. Feels instant. Used in React Query's optimistic updates and React 19 useOptimistic hook.
Example
// React 19 useOptimistic\nconst [optimisticLikes, addOptimisticLike] = useOptimistic(\n  likes,\n  (state, newLike) => [...state, newLike]\n);
45

What is the difference between React portals and normal rendering?

Portals render a component into a different DOM node than its parent, while keeping it in the React component tree. Used for modals, tooltips, and dropdowns that need to escape overflow:hidden or z-index constraints.

Example
function Modal({ children }) {\n  return ReactDOM.createPortal(\n    <div className="modal">{children}</div>,\n    document.getElementById("modal-root")\n  );\n}
46

What is the difference between React 18 flushSync and normal state updates?

flushSync forces React to flush all pending state updates synchronously before returning. Use it when you need the DOM to update immediately (e.g., before reading a DOM measurement). Overuse hurts performance.

Example
import { flushSync } from "react-dom";\n\nflushSync(() => {\n  setCount(1); // DOM updated synchronously before next line\n});\nconsole.log(ref.current.textContent); // sees updated DOM
47

What is the difference between React.createContext and useContext?

  • React.createContext(defaultValue) - creates a Context object with a Provider and Consumer. The defaultValue is used only when a component has no matching Provider above it.
  • useContext(Context) - subscribes a component to the context value. Re-renders whenever the context value changes.
48

What is the difference between error boundaries and try/catch in React?

Error boundaries are class components (or react-error-boundary library) that catch JavaScript errors in their child component tree during rendering, lifecycle methods, and constructors. try/catch only works for imperative code and event handlers — it cannot catch errors in render.

Example
import { ErrorBoundary } from "react-error-boundary";\n\n<ErrorBoundary fallback={<ErrorPage />}>\n  <App />\n</ErrorBoundary>
49

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

PureComponent implements shouldComponentUpdate with a shallow comparison of props and state, preventing re-renders when nothing has changed. Component always re-renders when setState is called. In functional components, React.memo is the equivalent of PureComponent.

50

What is the difference between hydration and rendering in React?

Rendering creates the DOM from scratch (CSR). Hydration attaches React event listeners to server-rendered HTML without recreating the DOM. React 18 introduces selective hydration — high-priority parts hydrate first, and Suspense boundaries can defer hydration of less important parts.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.