Top 100 React Interview Questions

An essential guide to React for frontend developers. Covering Hooks, state management, components, performance, and more.

This guide provides a curated list of common React interview questions to help you prepare for your next frontend developer role. Master these concepts, from core principles to advanced patterns, to demonstrate your expertise in building modern, scalable web applications with React.

Last Updated: Aug 20, 2025

Table of Contents

Core React Concepts

1. What is React?

React is a free and open-source front-end JavaScript library for building user interfaces based on UI components. It is maintained by Meta and a community of individual developers and companies. You can learn more from the official React documentation.

React can be used as a base in the development of single-page, mobile, or server-rendered applications with frameworks like Next.js.

2. What is JSX?

JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file. While it's not required to use React, it's the recommended approach as it makes writing React components easier and more intuitive.

A JSX expression like <h1>Hello</h1> is compiled by tools like Babel into a React.createElement('h1', null, 'Hello') call. This allows you to leverage the full power of JavaScript within your markup.

3. What is the Virtual DOM?

The Virtual DOM (VDOM) is a programming concept where a virtual representation of a UI is kept in memory and synced with the "real" DOM. When a component's state changes, React creates a new virtual DOM tree. It then compares this new tree with the previous one (a process called "diffing") and calculates the most efficient way to update the real DOM to match the new state. This minimizes direct DOM manipulation, which is often a performance bottleneck.

4. What are the key features of React?

  • Component-Based: Build encapsulated components that manage their own state
  • Virtual DOM: Improves performance by minimizing direct DOM manipulation
  • Declarative: Describe what the UI should look like for different states
  • Unidirectional Data Flow: Data flows down from parent to child components
  • JSX: JavaScript syntax extension that allows writing HTML-like code
  • React Native: Use React to build native mobile applications

5. What is the difference between Real DOM and Virtual DOM?

Real DOM Virtual DOM
Updates slowly Updates faster
Directly manipulates HTML Cannot directly update HTML
Creates a new DOM if element updates Updates JSX if element updates
DOM manipulation is expensive DOM manipulation is efficient
Too much memory wastage No memory wastage

6. What is the difference between a library and a framework?

React is a library, not a framework. The key difference is:

  • Library: You call the library (e.g., React controls your app when you call its methods)
  • Framework: The framework calls your code (e.g., Angular controls your app and calls your code when needed)

React focuses specifically on building user interfaces and can be integrated into various projects, while frameworks like Angular provide a more complete solution with built-in tools and patterns.

7. What are the advantages of using React?

  • Component Reusability: Components can be reused across the application
  • Performance: Virtual DOM ensures efficient updates
  • SEO Friendly: React can render on the server using Next.js
  • Large Community: Extensive ecosystem and support
  • Developer Tools: Excellent debugging tools like React DevTools
  • Mobile Development: React Native for building mobile apps
  • Easy to Learn: Simpler learning curve compared to other frameworks

8. What are the limitations of React?

  • Just a UI library, not a full framework
  • Learning JSX can be challenging for new developers
  • Rapid changes require continuous learning
  • Poor documentation for some advanced concepts
  • Requires additional libraries for routing, state management, etc.

9. What is the significance of keys in React?

Keys help React identify which items have changed, been added, or been removed. They should be given to the elements inside an array to give the elements a stable identity.

Keys should be unique among siblings but don't need to be globally unique. Using indexes as keys is not recommended if the order of items may change, as this can negatively impact performance and cause issues with component state.

10. What are synthetic events in React?

Synthetic events are cross-browser wrappers around the browser's native events. They have the same interface as native events but work identically across all browsers.

React normalizes events so that they have consistent properties across different browsers. The event handlers are passed instances of SyntheticEvent, which is React's cross-browser wrapper around the browser's native event.

Components & Props

11. What is a React component?

Components are independent, reusable pieces of UI that return React elements to be rendered to the DOM. They are the building blocks of React applications.

There are two main types of components:

  • Function Components: JavaScript functions that return JSX
  • Class Components: ES6 classes that extend React.Component

12. What is the difference between function components and class components?

Function Components Class Components
Plain JavaScript functions Require extending from React.Component
Use hooks to manage state Use this.state and this.setState()
No lifecycle methods, use useEffect Have lifecycle methods like componentDidMount
Easier to read and test More boilerplate code
Recommended approach for new code Legacy approach, still supported

13. What are props in React?

Props (short for properties) are read-only inputs to a React component. They are passed from parent to child components and help make components reusable.

Props are immutable - a component cannot change its props, only react to changes in them. They allow data to flow downward from parent to child components.

14. What is the difference between state and props?

State Props
Mutable (can be changed) Immutable (read-only)
Managed within the component Passed from parent component
Can be initialized and updated Can only be initialized by parent
Changes trigger re-rendering Changes trigger re-rendering
Local to the component Can be passed to child components

15. What are default props?

Default props allow you to set default values for props in a component. They are used when a parent component doesn't pass a prop to a child component.

For function components:

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

Greeting.defaultProps = {
  name: 'Guest'
};

For class components:

class Greeting extends React.Component {
  static defaultProps = {
    name: 'Guest'
  }

  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

16. What are PropTypes?

PropTypes are a way to type-check the props passed to a component. They help catch bugs by ensuring components receive props of the correct type.

import PropTypes from 'prop-types';

function User({ name, age, isVerified }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>Age: {age}</p>
      {isVerified && <span>Verified</span>}
    </div>
  );
}

User.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  isVerified: PropTypes.bool
};

User.defaultProps = {
  isVerified: false
};

17. What are Higher-Order Components (HOC)?

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

HOCs are used for:

  • Code reuse and logic abstraction
  • Props manipulation
  • State abstraction
  • Render hijacking
function withLogger(WrappedComponent) {
  return function(props) {
    console.log('Rendering:', WrappedComponent.name);
    return <WrappedComponent {...props} />;
  };
}

const EnhancedComponent = withLogger(MyComponent);

18. What are Pure Components?

Pure Components are similar to regular components but optimize performance by implementing a shallow comparison of props and state in the shouldComponentUpdate method.

For class components:

class PureComponent extends React.PureComponent {
  render() {
    return <div>{this.props.value}</div>;
  }
}

For function components, you can use React.memo:

const MemoizedComponent = React.memo(function MyComponent(props) {
  return <div>{props.value}</div>;
});

19. What are controlled and uncontrolled components?

  • Controlled Components: Form data is handled by React state. The component re-renders when the form data changes.
  • Uncontrolled Components: Form data is handled by the DOM itself. You use refs to access form values.

Controlled component example:

function ControlledForm() {
  const [value, setValue] = useState('');

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  return <input type="text" value={value} onChange={handleChange} />;
}

Uncontrolled component example:

function UncontrolledForm() {
  const inputRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(inputRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={inputRef} />
      <button type="submit">Submit</button>
    </form>
  );
}

20. What are error boundaries in React?

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.

They catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

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

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

  componentDidCatch(error, errorInfo) {
    console.log('Error:', error, errorInfo);
  }

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

    return this.props.children;
  }
}

// Usage
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

State & Lifecycle

21. What is state in React?

State is a built-in React object that contains data or information about the component. A component's state can change over time, and whenever it changes, the component re-renders.

State is similar to props, but it is private and fully controlled by the component. Unlike props, state can be modified using the setState() method (in class components) or the useState hook (in function components).

22. How do you update state in React?

In class components, you use this.setState():

this.setState({ count: this.state.count + 1 });

In function components, you use the useState hook:

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

State updates may be asynchronous, so when updating state based on previous state, use the function form:

// Class component
this.setState(prevState => ({ count: prevState.count + 1 }));

// Function component
setCount(prevCount => prevCount + 1);

23. What is the component lifecycle in React?

The component lifecycle refers to the series of methods that are invoked in different stages of a component's existence. There are three main phases:

  1. Mounting: When a component is being created and inserted into the DOM
  2. Updating: When a component is being re-rendered as a result of changes to either its props or state
  3. Unmounting: When a component is being removed from the DOM

24. What are the lifecycle methods in class components?

Mounting:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

Updating:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

Unmounting:

  • componentWillUnmount()

Error Handling:

  • static getDerivedStateFromError()
  • componentDidCatch()

25. How do you perform side effects in function components?

You use the useEffect hook to perform side effects in function components:

import { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    // Side effect code here
    document.title = 'My Page Title';

    // Cleanup function (optional)
    return () => {
      document.title = 'Previous Title';
    };
  }, []); // Dependency array

  return <div>My Component</div>;
}

The dependency array controls when the effect runs:

  • Empty array []: Runs only once after initial render
  • No array: Runs after every render
  • With values [a, b]: Runs when any dependency changes

26. What is the purpose of the dependency array in useEffect?

The dependency array tells React when to re-run the effect. It contains values that the effect depends on:

  • Empty array []: Effect runs only once after the initial render
  • No array: Effect runs after every render
  • With values [a, b]: Effect runs when any of the specified values change

React compares the current values with the previous values using Object.is comparison. If any value has changed, the effect runs again.

27. How do you prevent unnecessary re-renders?

Several techniques to prevent unnecessary re-renders:

  • Use React.memo() for function components
  • Use PureComponent for class components
  • Use useCallback() to memoize functions
  • Use useMemo() to memoize values
  • Implement shouldComponentUpdate() in class components
  • Split components to isolate state changes

28. What is Lifting State Up?

Lifting state up is a pattern where you move the state from a child component to a common parent component, so multiple children can share and synchronize the same state.

This is useful when:

  • Multiple components need to reflect the same changing data
  • Components need to be kept in sync with each other
  • You need a single source of truth for shared state

29. What is the difference between useState and useReducer?

useState useReducer
Simple state management Complex state logic
Direct value updates Action-based updates
Good for independent values Good for related values
Less boilerplate More boilerplate
setState(newValue) dispatch(action)

30. How do you handle forms in React?

There are two main approaches to handling forms in React:

  1. Controlled Components: Form data is handled by React state
  2. Uncontrolled Components: Form data is handled by the DOM itself

Controlled component example:

function LoginForm() {
  const [formData, setFormData] = useState({
    username: '',
    password: ''
  });

  const handleChange = (e) => {
    setFormData({
      ...formData,
      [e.target.name]: e.target.value
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        name="username"
        value={formData.username}
        onChange={handleChange}
      />
      <input
        type="password"
        name="password"
        value={formData.password}
        onChange={handleChange}
      />
      <button type="submit">Login</button>
    </form>
  );
}

React Hooks

31. What are React Hooks?

Hooks are functions that let you "hook into" React state and lifecycle features from function components. They were introduced in React 16.8 to allow using state and other React features without writing class components.

Basic rules of hooks:

  • Only call hooks at the top level (not in loops, conditions, or nested functions)
  • Only call hooks from React function components or custom hooks

32. What is the useState hook?

The useState hook allows you to add state to function components. It returns a stateful value and a function to update it.

import { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

You can use the function form for updates based on previous state:

setCount(prevCount => prevCount + 1);

33. What is the useEffect hook?

The useEffect hook lets you perform side effects in function components. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in class components.

import { useEffect, useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Fetch user data when userId changes
    fetchUser(userId).then(setUser);

    // Cleanup function
    return () => {
      // Cancel any ongoing requests
    };
  }, [userId]); // Only re-run if userId changes

  if (!user) return <div>Loading...</div>;

  return <div>{user.name}</div>;
}

34. What is the useContext hook?

The useContext hook lets you subscribe to React context without introducing nesting. It accepts a context object and returns the current context value.

import { createContext, useContext } from 'react';

// Create context
const ThemeContext = createContext('light');

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

function Toolbar() {
  return <ThemedButton />;
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Themed Button</button>;
}

35. What is the useReducer hook?

useReducer is an alternative to useState for managing complex state logic. It's similar to Redux and is useful when state transitions are complex or when the next state depends on the previous one.

import { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

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

  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

36. What is the useCallback hook?

useCallback returns a memoized callback function. It's useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.

import { useCallback, useState } from 'react';

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

  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []); // Empty dependency array means this never changes

  return <Child onIncrement={increment} />;
}

const Child = React.memo(function Child({ onIncrement }) {
  return <button onClick={onIncrement}>Increment</button>;
});

37. What is the useMemo hook?

useMemo returns a memoized value. It's useful for expensive calculations that you want to avoid re-running on every render.

import { useMemo } from 'react';

function ExpensiveComponent({ list, filter }) {
  const filteredList = useMemo(() => {
    return list.filter(item => item.includes(filter));
  }, [list, filter]); // Only recalculate when list or filter changes

  return <div>{filteredList.join(', ')}</div>;
}

38. What is the useRef hook?

useRef returns a mutable ref object whose .current property is initialized to the passed argument. It's useful for accessing DOM elements or storing mutable values that don't trigger re-renders.

import { useRef, useEffect } from 'react';

function TextInputWithFocusButton() {
  const inputEl = useRef(null);

  const onButtonClick = () => {
    inputEl.current.focus();
  };

  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </div>
  );
}

39. What is the useLayoutEffect hook?

useLayoutEffect is similar to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render.

Use cases:

  • Measuring DOM elements
  • Animations that need to start immediately
  • Operations that need to complete before the browser paints
import { useLayoutEffect, useRef } from 'react';

function Tooltip() {
  const ref = useRef(null);

  useLayoutEffect(() => {
    const { height } = ref.current.getBoundingClientRect();
    // Do something with the height before browser paint
  }, []);

  return <div ref={ref}>Tooltip content</div>;
}

40. What are custom hooks?

Custom hooks are JavaScript functions whose names start with "use" and that may call other hooks. They let you extract component logic into reusable functions.

import { useState, useEffect } from 'react';

// Custom hook
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.log(error);
    }
  };

  return [storedValue, setValue];
}

// Usage
function Component() {
  const [name, setName] = useLocalStorage('name', 'John');

  return (
    <input
      value={name}
      onChange={e => setName(e.target.value)}
    />
  );
}

41. What is the useImperativeHandle hook?

useImperativeHandle customizes the instance value that is exposed to parent components when using ref. It should be used with forwardRef.

import { forwardRef, useImperativeHandle, useRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();

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

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

// Parent component can now call inputRef.current.focus()
function Parent() {
  const inputRef = useRef();

  return (
    <div>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus</button>
    </div>
  );
}

42. What is the useDebugValue hook?

useDebugValue can be used to display a label for custom hooks in React DevTools. It's useful for debugging custom hooks.

import { useDebugValue, useState } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // Display this label in DevTools next to this Hook
  useDebugValue(isOnline ? 'Online' : 'Offline');

  return isOnline;
}

43. What is the useId hook?

useId generates unique IDs that are stable across server and client renders, avoiding hydration mismatches. It's useful for accessibility attributes.

import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();

  return (
    <div>
      <label>
        Password:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 8 characters
      </p>
    </div>
  );
}

44. What is the useTransition hook?

useTransition lets you mark some state updates as non-urgent, allowing other updates to interrupt them. This helps keep the UI responsive during heavy rendering.

import { useTransition, useState } from 'react';

function TabContainer() {
  const [isPending, startTransition] = useTransition();
  const [tab, setTab] = useState('home');

  function selectTab(nextTab) {
    startTransition(() => {
      setTab(nextTab);
    });
  }

  return (
    <div>
      {isPending && <Spinner />}
      <TabButton isActive={tab === 'home'} onClick={() => selectTab('home')}>
        Home
      </TabButton>
      <TabButton isActive={tab === 'about'} onClick={() => selectTab('about')}>
        About
      </TabButton>
    </div>
  );
}

45. What is the useDeferredValue hook?

useDeferredValue lets you defer updating a non-urgent part of the UI. It's similar to debouncing but integrated with React's rendering cycle.

import { useDeferredValue, useState, memo } from 'react';

function SearchResults({ query }) {
  const deferredQuery = useDeferredValue(query);

  return (
    <div>
      <Suggestions query={deferredQuery} />
    </div>
  );
}

const Suggestions = memo(function Suggestions({ query }) {
  // This will re-render only when deferredQuery changes
  const suggestions = getSuggestions(query);

  return <ul>{suggestions.map(suggestion =>
    <li key={suggestion.id}>{suggestion.text}</li>
  )}</ul>;
});

Styling in React

46. What are the different ways to style React components?

There are several approaches to styling React components:

  • Inline Styles: Using the style attribute with JavaScript objects
  • CSS Classes: Regular CSS with className attribute
  • CSS Modules: Locally scoped CSS classes
  • Styled Components: CSS-in-JS library
  • CSS-in-JS Libraries: Emotion, Styled-JSX, etc.
  • UI Frameworks: Material-UI, Ant Design, Chakra UI, etc.
  • SASS/LESS: CSS preprocessors

47. What are CSS Modules?

CSS Modules are CSS files in which all class names and animation names are scoped locally by default. They help avoid class name collisions.

/* styles.module.css */
.button {
  background: blue;
  color: white;
}

// Component.js
import styles from './styles.module.css';

function Button() {
  return <button className={styles.button}>Click me</button>;
}

The generated HTML will have a unique class name like button_abc123.

48. What are Styled Components?

Styled Components is a CSS-in-JS library that lets you write actual CSS code to style your components. It removes the mapping between components and styles.

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? 'blue' : 'white'};
  color: ${props => props.primary ? 'white' : 'blue'};
  font-size: 1em;
  padding: 0.25em 1em;
  border: 2px solid blue;
  border-radius: 3px;
`;

function App() {
  return (
    <div>
      <Button>Normal</Button>
      <Button primary>Primary</Button>
    </div>
  );
}

49. How do you handle responsive design in React?

Several approaches for responsive design in React:

  • CSS Media Queries: Traditional approach with CSS
  • React Responsive: Library with useMediaQuery hook
  • Conditional Rendering: Render different components based on screen size
  • CSS Frameworks: Bootstrap, Tailwind CSS, etc.
import { useMediaQuery } from 'react-responsive';

function Component() {
  const isMobile = useMediaQuery({ query: '(max-width: 768px)' });

  return (
    <div>
      {isMobile ? <MobileView /> : <DesktopView />}
    </div>
  );
}

50. What is the CSS-in-JS pattern?

CSS-in-JS is a pattern where CSS is composed using JavaScript instead of defined in external files. Key benefits:

  • Scoped styles (no class name collisions)
  • Dynamic styling based on props/state
  • Automatic vendor prefixing
  • Automatic critical CSS extraction
  • Theming support

Popular CSS-in-JS libraries include Styled Components, Emotion, and Styled-JSX.

React Router

51. What is React Router?

React Router is the standard routing library for React. It enables navigation between views of different components, allows changing the browser URL, and keeps the UI in sync with the URL.

Key components:

  • BrowserRouter: Uses HTML5 history API
  • Route: Renders UI when path matches
  • Link: Navigation without page reload
  • Switch: Renders the first matching Route
  • Redirect: Navigates to a new location

52. How do you set up routing in React?

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

function App() {
  return (
    <Router>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
      </nav>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Router>
  );
}

function Home() {
  return <h1>Home</h1>;
}

function About() {
  return <h1>About</h1>;
}

53. How do you handle route parameters?

Use the useParams hook to access route parameters:

import { Routes, Route, useParams } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/users/:id" element={<UserProfile />} />
    </Routes>
  );
}

function UserProfile() {
  let { id } = useParams();

  return <h1>User ID: {id}</h1>;
}

54. How do you implement programmatic navigation?

Use the useNavigate hook for programmatic navigation:

import { useNavigate } from 'react-router-dom';

function LoginForm() {
  let navigate = useNavigate();

  const handleLogin = () => {
    // Perform login logic
    navigate('/dashboard');
  };

  return (
    <form onSubmit={handleLogin}>
      <button type="submit">Login</button>
    </form>
  );
}

55. How do you handle nested routes?

Nested routes allow you to render components within other components based on the URL:

import { Routes, Route, Outlet } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/dashboard" element={<Dashboard />}>
        <Route path="profile" element={<Profile />} />
        <Route path="settings" element={<Settings />} />
      </Route>
    </Routes>
  );
}

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <nav>
        <Link to="profile">Profile</Link>
        <Link to="settings">Settings</Link>
      </nav>

      <Outlet /> {/* This is where nested routes render */}
    </div>
  );
}

State Management

56. What is state management in React?

State management refers to how you manage and share state across components in your application. While React's built-in state is sufficient for simple applications, larger applications often need more sophisticated state management solutions.

Common state management approaches:

  • React Context API
  • Redux
  • MobX
  • Zustand
  • Recoil
  • Jotai

57. What is the Context API?

The Context API provides a way to pass data through the component tree without having to pass props down manually at every level. It's useful for global data that many components need access to.

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

const ThemeContext = createContext();

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

  const toggleTheme = () => {
    setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
  };

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

function useTheme() {
  return useContext(ThemeContext);
}

function ThemedButton() {
  const { theme, toggleTheme } = useTheme();

  return (
    <button onClick={toggleTheme} className={theme}>
      Toggle Theme
    </button>
  );
}

58. What is Redux?

Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments, and are easy to test.

Core concepts:

  • Store: Single source of truth for state
  • Actions: Plain objects describing what happened
  • Reducers: Pure functions that specify how state changes
  • Dispatch: Function to send actions to the store

59. What is the difference between Context API and Redux?

Context API Redux
Built into React External library
Good for low-frequency updates Good for complex state interactions
Minimal setup More boilerplate
No middleware support Middleware support (thunk, saga, etc.)
No DevTools Powerful DevTools

60. What is Redux Toolkit?

Redux Toolkit is the official, opinionated, batteries-included toolset for efficient Redux development. It simplifies many common Redux use cases and follows best practices by default.

Key features:

  • configureStore(): Simplified store setup
  • createReducer(): Creates reducers with Immer
  • createAction(): Creates action creators
  • createSlice(): Combines actions and reducers
  • createAsyncThunk(): Handles async requests

61. What are React state management best practices?

  • Keep state as close as possible to where it's needed
  • Lift state up when multiple components need the same data
  • Use Context API for global state that doesn't change often
  • Use Redux for complex state with frequent updates
  • Normalize state shape for better performance
  • Use selectors for derived data
  • Keep state minimal - don't store computed data

62. What is Zustand?

Zustand is a small, fast, and scalable state management solution with a comfy API based on hooks. It's less boilerplate than Redux and doesn't require context providers.

import create from 'zustand';

const useStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}));

function BearCounter() {
  const bears = useStore((state) => state.bears);
  return <h1>{bears} bears around here...</h1>;
}

function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation);
  return <button onClick={increasePopulation}>Add bear</button>;
}

63. What is Recoil?

Recoil is a state management library for React developed by Facebook. It provides several capabilities that are difficult to achieve with React alone while being compatible with the newest features of React.

Key concepts:

  • Atoms: Pieces of state
  • Selectors: Derived state
  • Hooks: useRecoilState, useRecoilValue, useSetRecoilState

64. What is MobX?

MobX is a simple, scalable, and battle-tested state management solution that makes state management simple and scalable by transparently applying functional reactive programming.

Core concepts:

  • Observable state
  • Actions that modify state
  • Reactions that automatically update when state changes

65. When should you use external state management?

Consider using external state management when:

  • State needs to be shared across many components
  • State is complex with many interactions
  • You need to persist state across sessions
  • You need time-travel debugging
  • You have complex async data flows
  • Application performance is suffering from prop drilling

Performance Optimization

66. How do you optimize React application performance?

React performance optimization techniques:

  • Use React.memo() for function components
  • Use PureComponent for class components
  • Use useCallback() to memoize functions
  • Use useMemo() to memoize values
  • Implement shouldComponentUpdate() in class components
  • Code splitting with React.lazy() and Suspense
  • Virtualize long lists with react-window
  • Optimize images and assets
  • Use production builds

67. What is React.memo()?

React.memo() is a higher-order component that memoizes the result of a function component. It only re-renders the component if its props change.

const MyComponent = React.memo(function MyComponent(props) {
  // Only re-renders if props change
  return <div>{props.value}</div>;
});

You can also provide a custom comparison function:

const MyComponent = React.memo(
  function MyComponent(props) {
    return <div>{props.value}</div>;
  },
  (prevProps, nextProps) => {
    // Return true if passing nextProps would return
    // the same result as passing prevProps
    return prevProps.value === nextProps.value;
  }
);

68. What is code splitting and how do you implement it?

Code splitting is the process of splitting your code into smaller bundles that can be loaded on demand. This improves the initial load time of your application.

Using React.lazy() and Suspense:

import { Suspense, lazy } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

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

Using dynamic import with Webpack:

import('./math').then(math => {
  console.log(math.add(16, 26));
});

69. What is lazy loading in React?

Lazy loading is a technique to delay loading components until they are needed. This reduces the initial bundle size and improves load time.

React provides React.lazy() for lazy loading components:

import { Suspense, lazy } from 'react';

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

70. How do you optimize rendering of large lists?

To optimize rendering of large lists:

  • Use windowing/virtualization with libraries like react-window
  • Implement pagination
  • Use React.memo() for list items
  • Avoid inline functions and objects in props
  • Use key prop correctly
import { FixedSizeList as List } from 'react-window';

const Row = ({ index, style }) => (
  <div style={style}>Row {index}</div>
);

function BigList() {
  return (
    <List
      height={400}
      itemCount={1000}
      itemSize={35}
      width={300}
    >
      {Row}
    </List>
  );
}

71. What are the common performance pitfalls in React?

  • Unnecessary re-renders due to incorrect prop comparisons
  • Large bundle sizes without code splitting
  • Inefficient list rendering without virtualization
  • Memory leaks from uncleaned effects
  • Inline function creation in render causing unnecessary re-renders
  • Overusing Context for frequently updated data
  • Not using production builds

72. How do you use the React Profiler?

The React Profiler measures how often components render and what "costs" they have. You can use it to identify performance bottlenecks.

import { Profiler } from 'react';

function onRenderCallback(
  id, // the "id" prop of the Profiler tree
  phase, // "mount" or "update"
  actualDuration, // time spent rendering
  baseDuration, // estimated time without memoization
  startTime, // when React began rendering
  commitTime, // when React committed
  interactions // which interactions were part of this update
) {
  console.log('Render time:', actualDuration);
}

function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <YourComponents />
    </Profiler>
  );
}

73. What is the use of the key prop in lists?

The key prop helps React identify which items have changed, been added, or been removed. Keys should be stable, predictable, and unique among siblings.

Good practices:

  • Use unique IDs from your data as keys
  • Avoid using array indexes as keys if the order can change
  • Keys should be consistent across re-renders
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo =>
        <li key={todo.id}>{todo.text}</li>
      )}
    </ul>
  );
}

74. How do you prevent memory leaks in React?

To prevent memory leaks:

  • Clean up effects with return functions in useEffect
  • Cancel API requests when components unmount
  • Remove event listeners in cleanup functions
  • Clear timeouts and intervals
  • Avoid storing large objects in state unnecessarily
useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;

  fetchData(signal).then(data => {
    if (!signal.aborted) {
      setData(data);
    }
  });

  return () => {
    controller.abort();
  };
}, []);

75. What is the production build and how does it optimize performance?

The production build is an optimized version of your React app that includes:

  • Minified code (smaller file sizes)
  • Dead code elimination (tree shaking)
  • Optimized assets (compressed images, etc.)
  • Faster rendering without development checks
  • Better caching with content hashes

To create a production build:

npm run build  # Create React App
yarn build     # Create React App
npm run build  # Next.js
yarn build     # Next.js

Testing

76. How do you test React components?

Common approaches to testing React components:

  • Jest: JavaScript testing framework
  • React Testing Library: DOM testing utilities
  • Enzyme: Testing utility for React (legacy)
  • Cypress: End-to-end testing
  • Storybook: Component development and testing

77. What is React Testing Library?

React Testing Library is a set of utilities that encourage testing components in a way that resembles how users interact with your application.

Key principles:

  • Test components from the user's perspective
  • Avoid testing implementation details
  • Focus on what users see and interact with
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Button from './Button';

test('renders button with text', () => {
  render(<Button>Click me</Button>);
  const button = screen.getByText(/click me/i);
  expect(button).toBeInTheDocument();
});

test('calls onClick when clicked', async () => {
  const handleClick = jest.fn();
  render(<Button onClick={handleClick}>Click me</Button>);

  const button = screen.getByText(/click me/i);
  await userEvent.click(button);

  expect(handleClick).toHaveBeenCalledTimes(1);
});

78. How do you test hooks?

You can test hooks using React Testing Library's renderHook function:

import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';

test('should increment counter', () => {
  const { result } = renderHook(() => useCounter());

  act(() => {
    result.current.increment();
  });

  expect(result.current.count).toBe(1);
});

For custom hooks that depend on context, you can wrap them in a provider:

test('should use theme context', () => {
  const wrapper = ({ children }) => (
    <ThemeProvider value="dark">{children}</ThemeProvider>
  );

  const { result } = renderHook(() => useTheme(), { wrapper });

  expect(result.current).toBe('dark');
});

79. How do you mock API calls in tests?

You can mock API calls using Jest's mocking capabilities:

import { render, screen, waitFor } from '@testing-library/react';
import axios from 'axios';
import UserList from './UserList';

jest.mock('axios');

test('renders users', async () => {
  const users = [{ id: 1, name: 'John' }];
  axios.get.mockResolvedValue({ data: users });

  render(<UserList />);

  await waitFor(() => {
    expect(screen.getByText('John')).toBeInTheDocument();
  });
});

You can also use MSW (Mock Service Worker) for more realistic API mocking:

import { setupServer } from 'msw/node';
import { rest } from 'msw';

const server = setupServer(
  rest.get('/api/users', (req, res, ctx) => {
    return res(ctx.json([{ id: 1, name: 'John' }]));
  })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

80. What are snapshot tests?

Snapshot tests capture the rendered output of a component and compare it to a stored reference snapshot. If the output changes, the test fails.

import renderer from 'react-test-renderer';
import Button from './Button';

test('renders correctly', () => {
  const tree = renderer
    .create(<Button>Click me</Button>)
    .toJSON();

  expect(tree).toMatchSnapshot();
});

When a component changes, you can update the snapshot with:

npm test -- --updateSnapshot
# or
jest --updateSnapshot

Snapshot tests are useful for preventing unintended changes to UI, but they shouldn't be the only type of test you write.

Advanced & Ecosystem

81. What is Server-Side Rendering (SSR)?

Server-Side Rendering is the process of rendering React components on the server and sending the fully-rendered HTML to the client. This improves:

  • SEO (search engines can crawl the content)
  • Initial load performance (users see content faster)
  • Social media sharing (proper meta tags)

Popular SSR solutions for React:

  • Next.js (most popular)
  • Gatsby (for static sites)
  • Remix
  • Custom SSR with Express and ReactDOMServer

82. What is Static Site Generation (SSG)?

Static Site Generation is the process of pre-rendering pages at build time. The HTML is generated once and served to all users.

Benefits:

  • Excellent performance (pre-built HTML)
  • Better SEO
  • Easier caching and CDN distribution
  • More secure (no server-side code execution)

Frameworks that support SSG:

  • Next.js (with getStaticProps)
  • Gatsby
  • Nuxt.js (for Vue, but similar concept)

83. What is Next.js?

Next.js is a React framework that provides:

  • Server-side rendering
  • Static site generation
  • API routes
  • File-based routing
  • Built-in CSS and Sass support
  • Automatic code splitting
  • Optimized performance

Next.js simplifies React development by providing a structured framework with many built-in features that would otherwise require complex configuration.

84. What are React Server Components?

React Server Components are a new experimental feature that allows components to be rendered on the server and streamed to the client. They enable:

  • Zero bundle size for server components
  • Direct access to backend resources
  • Automatic code splitting
  • Seamless combination with client components

Server Components are still experimental but are available in Next.js 13+ with the App Router.

85. What is React Suspense?

React Suspense lets components "wait" for something before rendering. It's primarily used for:

  • Code splitting (with React.lazy)
  • Data fetching
  • Waiting for animations
import { Suspense } from 'react';

function ProfilePage() {
  return (
    <Suspense fallback={<h1>Loading profile...</h1>}>
      <ProfileDetails />
    </Suspense>
  );
}

Suspense for data fetching is still experimental but provides a declarative way to handle async operations.

86. What are React Portals?

React Portals provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

Use cases:

  • Modals
  • Tooltips
  • Popovers
  • Dialogs
import { createPortal } from 'react-dom';

function Modal({ children }) {
  return createPortal(
    children,
    document.getElementById('modal-root')
  );
}

function App() {
  return (
    <div>
      <Modal>
        <h1>Modal Content</h1>
      </Modal>
    </div>
  );
}

87. What are React Error Boundaries?

Error Boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.

They catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

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

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

  componentDidCatch(error, errorInfo) {
    logErrorToService(error, errorInfo);
  }

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

    return this.props.children;
  }
}

// Usage
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

88. What are React Fragments?

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

function List() {
  return (
    <React.Fragment>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </React.Fragment>
  );
}

// Short syntax
function List() {
  return (
    <>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </>
  );
}

Fragments are useful when you need to return multiple elements from a component but don't want to wrap them in a unnecessary DOM element.

89. What are React Refs?

Refs provide a way to access DOM nodes or React elements created in the render method. They are useful for:

  • Managing focus, text selection, or media playback
  • Triggering imperative animations
  • Integrating with third-party DOM libraries
function TextInput() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus input</button>
    </div>
  );
}

90. What is React.StrictMode?

React.StrictMode is a tool for highlighting potential problems in an application. It activates additional checks and warnings for its descendants.

StrictMode helps with:

  • Identifying unsafe lifecycle methods
  • Warning about legacy string ref API usage
  • Detecting unexpected side effects
  • Detecting legacy context API
function App() {
  return (
    <React.StrictMode>
      <div>
        <ComponentOne />
        <ComponentTwo />
      </div>
    </React.StrictMode>
  );
}

StrictMode checks are only run in development mode and do not impact the production build.

91. What are React hooks rules?

The Rules of Hooks are:

  1. Only call hooks at the top level. Don't call hooks inside loops, conditions, or nested functions.
  2. Only call hooks from React function components or custom hooks. Don't call hooks from regular JavaScript functions.

React relies on the order in which hooks are called to preserve state between re-renders. Violating these rules can lead to bugs.

92. What is the React ecosystem?

The React ecosystem includes:

  • Frameworks: Next.js, Gatsby, Remix
  • State Management: Redux, MobX, Zustand, Recoil
  • Routing: React Router, Next.js Router
  • Styling: Styled Components, Emotion, CSS Modules
  • Testing: Jest, React Testing Library, Cypress
  • UI Libraries: Material-UI, Ant Design, Chakra UI
  • Forms: Formik, React Hook Form
  • Data Fetching: React Query, SWR, Apollo Client
  • Animation: Framer Motion, React Spring

93. What is React Query (TanStack Query)?

React Query is a library for managing server state in React applications. It provides:

  • Data fetching and caching
  • Background updates
  • Pagination and infinite queries
  • Mutations (create, update, delete operations)
  • Optimistic updates
  • Prefetching
import { useQuery } from '@tanstack/react-query';

function Todos() {
  const { isLoading, error, data } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/api/todos').then(res => res.json())
  });

  if (isLoading) return 'Loading...';
  if (error) return 'An error occurred';

  return (
    <ul>
      {data.map(todo => <li key={todo.id}>{todo.title}</li>)}
    </ul>
  );
}

94. What is SWR?

SWR (Stale-While-Revalidate) is a React hooks library for data fetching. The name comes from the HTTP cache invalidation strategy.

Key features:

  • Fast, lightweight, and reusable data fetching
  • Built-in cache and request deduplication
  • Real-time experience
  • TypeScript ready
  • SSR/SSG support
import useSWR from 'swr';

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher);

  if (error) return <div>Failed to load</div>;
  if (!data) return <div>Loading...</div>;

  return <div>Hello {data.name}!</div>;
}

95. What is Formik?

Formik is a popular form library for React that helps with:

  • Form state management
  • Validation and error messages
  • Form submission
  • Handling form arrays
import { Formik, Form, Field, ErrorMessage } from 'formik';

function SignupForm() {
  return (
    <Formik
      initialValues={{ email: '', password: '' }}
      validate={values => {
        const errors = {};
        if (!values.email) errors.email = 'Required';
        else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
          errors.email = 'Invalid email address';
        }
        return errors;
      }}
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          setSubmitting(false);
        }, 400);
      }}
    >
      {({ isSubmitting }) => (
        <Form>
          <Field type="email" name="email" />
          <ErrorMessage name="email" component="div" />
          <Field type="password" name="password" />
          <ErrorMessage name="password" component="div" />
          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </Form>
      )}
    </Formik>
  );
}

96. What is React Hook Form?

React Hook Form is a performant, flexible, and extensible form library with easy-to-use validation. It minimizes the number of re-renders and provides a great developer experience.

import { useForm } from 'react-hook-form';

function Form() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName', { required: true })} />
      {errors.firstName && <span>This field is required</span>}

      <input {...register('lastName', { required: true })} />
      {errors.lastName && <span>This field is required</span>}

      <button type="submit">Submit</button>
    </form>
  );
}

97. What is React Spring?

React Spring is a spring-physics based animation library that gives fluid and natural animations. It's a modern alternative to CSS transitions and keyframes.

import { useSpring, animated } from 'react-spring';

function FadeIn() {
  const props = useSpring({
    from: { opacity: 0 },
    to: { opacity: 1 },
    config: { duration: 1000 }
  });

  return <animated.div style={props}>I will fade in</animated.div>;
}

98. What is Framer Motion?

Framer Motion is a production-ready motion library for React. It's simple yet powerful, allowing you to create complex animations with minimal code.

import { motion } from 'framer-motion';

function AnimatedBox() {
  return (
    <motion.div
      initial={{ opacity: 0, scale: 0.5 }}
      animate={{ opacity: 1, scale: 1 }}
      transition={{ duration: 0.5 }}
      whileHover={{ scale: 1.2 }}
      whileTap={{ scale: 0.8 }}
    >
      Animated Content
    </motion.div>
  );
}

99. What are React best practices?

  • Use functional components and hooks
  • Keep components small and focused
  • Use descriptive component and variable names
  • Use PropTypes or TypeScript for type checking
  • Extract reusable logic into custom hooks
  • Use React.memo, useCallback, and useMemo for performance
  • Implement error boundaries
  • Write tests for your components
  • Use a linter and formatter (ESLint, Prettier)
  • Follow accessibility guidelines

100. How do you stay updated with React changes?

To stay updated with React:

  • Follow the official React blog
  • Read release notes for new versions
  • Follow React team members on social media
  • Join React communities (Discord, Reddit, etc.)
  • Attend React conferences and meetups
  • Watch talks from React Conf
  • Read books and courses on modern React
  • Experiment with new features in side projects
  • Contribute to open source React projects
DevUtilityTool Logo

About the Author

This guide is curated by the team at DevUtilityTool, who are passionate about creating high-quality, accessible resources that help developers excel in their careers.