React45 min read

React.js Interview Questions: 50 Essential Questions for Developers

Comprehensive collection of 50 essential React.js interview questions covering hooks, components, state management, performance, and advanced concepts.

James Wilson
December 16, 2025
0.0k0

This comprehensive guide covers 50 essential React.js interview questions that every developer should know. These questions cover fundamental concepts, hooks, performance optimization, and advanced patterns commonly asked in technical interviews.

Core Concepts

Understanding React's core concepts is essential for any React developer. These questions test your knowledge of components, props, state, and the component lifecycle.

React Hooks

Hooks revolutionized React development by allowing functional components to use state and lifecycle features. Master these questions to demonstrate your understanding of modern React patterns.

Performance Optimization

React performance is crucial for building fast applications. These questions cover memoization, code splitting, lazy loading, and other optimization techniques.

Advanced Patterns

Advanced React patterns include context API, error boundaries, render props, higher-order components, and custom hooks. These questions test your ability to solve complex problems.

#React#Interview#Hooks#Components#State Management

Common Questions & Answers

Q1

What is React and what are its main features?

A

React is a JavaScript library for building user interfaces, particularly web applications. Its main features include component-based architecture, virtual DOM for efficient updates, one-way data binding, JSX syntax for writing HTML-like code in JavaScript, and a rich ecosystem of hooks and tools for state management and routing.

Q2

Explain the difference between functional and class components.

A

Functional components are JavaScript functions that return JSX. They are simpler, easier to test, and use hooks for state and lifecycle. Class components are ES6 classes that extend React.Component, use this.state and lifecycle methods. Functional components are now preferred in modern React development.

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

class ClassComponent extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
Q3

What is JSX and how does it differ from HTML?

A

JSX is a syntax extension for JavaScript that allows writing HTML-like code. It gets transpiled to React.createElement() calls. Differences include using className instead of class, camelCase for attributes like onClick, self-closing tags must have /, and JavaScript expressions are wrapped in curly braces.

javascript
const element = (
  <div className="container">
    <h1>Hello {user.name}</h1>
    <button onClick={handleClick}>Click Me</button>
    <img src={imageUrl} alt="Description" />
  </div>
);
Q4

What is the Virtual DOM and how does it work?

A

The Virtual DOM is a JavaScript representation of the real DOM. React creates a virtual representation, compares it with the previous version when state changes, identifies differences (diffing), and updates only the changed nodes in the real DOM (reconciliation). This makes updates faster than directly manipulating the DOM.

Q5

Explain React component lifecycle methods.

A

Lifecycle methods are hooks that allow you to run code at specific points in a component's lifecycle. In class components: componentDidMount (after first render), componentDidUpdate (after updates), componentWillUnmount (before removal). In functional components, useEffect hook replaces these methods.

javascript
class MyComponent extends React.Component {
  componentDidMount() {
    console.log('Component mounted');
  }
  
  componentDidUpdate(prevProps, prevState) {
    if (prevProps.count !== this.props.count) {
      console.log('Count changed');
    }
  }
  
  componentWillUnmount() {
    console.log('Component will unmount');
  }
  
  render() {
    return <div>{this.props.count}</div>;
  }
}
Q6

What are props in React and how do they differ from state?

A

Props are read-only data passed from parent to child components. They are immutable and flow downward. State is internal data managed within a component, can be changed using setState or useState, and triggers re-renders when updated. Props are for configuration, state is for dynamic data.

javascript
function Child({ name, age }) {
  return <div>{name} is {age} years old</div>;
}

function Parent() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <Child name="John" age={25} />
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
    </div>
  );
}
Q7

How does useState hook work?

A

useState is a hook that adds state to functional components. It returns an array with two elements: the current state value and a function to update it. The initial value is set once on mount. Calling the update function triggers a re-render with the new state value.

javascript
function Counter() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: '', email: '' });
  
  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };
  
  const updateUser = () => {
    setUser(prev => ({ ...prev, name: 'John' }));
  };
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
Q8

What is the purpose of useEffect hook?

A

useEffect performs side effects in functional components. It runs after render and can handle data fetching, subscriptions, DOM manipulation, and cleanup. The dependency array controls when it runs: empty array runs once on mount, with dependencies runs when they change, no array runs after every render.

javascript
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]);
  
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Timer tick');
    }, 1000);
    
    return () => clearInterval(timer);
  }, []);
  
  return user ? <div>{user.name}</div> : <div>Loading...</div>;
}
Q9

What is the difference between useEffect and useLayoutEffect?

A

useEffect runs asynchronously after the browser paints, while useLayoutEffect runs synchronously after DOM mutations but before the browser paints. Use useLayoutEffect when you need to read layout from DOM and synchronously re-render to prevent visual flashing. useEffect is preferred for most cases.

javascript
function Component() {
  const [width, setWidth] = useState(0);
  const divRef = useRef();
  
  useLayoutEffect(() => {
    setWidth(divRef.current.offsetWidth);
  }, []);
  
  return <div ref={divRef}>Width: {width}</div>;
}
Q10

How do you handle events in React?

A

React uses synthetic events, a wrapper around native events for cross-browser compatibility. Event handlers are passed as props with camelCase names like onClick, onChange. The event object is passed automatically. Use arrow functions or bind to maintain this context in class components.

javascript
function Button() {
  const handleClick = (e) => {
    e.preventDefault();
    console.log('Button clicked', e.target);
  };
  
  const handleChange = (e) => {
    console.log('Input value:', e.target.value);
  };
  
  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      <input onChange={handleChange} />
    </div>
  );
}
Q11

What are controlled and uncontrolled components?

A

Controlled components have form data handled by React state. The value is stored in state and updated via onChange. Uncontrolled components use refs to access form values directly from DOM. Controlled components are preferred for React applications.

javascript
function ControlledInput() {
  const [value, setValue] = useState('');
  
  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

function UncontrolledInput() {
  const inputRef = useRef();
  
  const handleSubmit = () => {
    console.log(inputRef.current.value);
  };
  
  return <input ref={inputRef} />;
}
Q12

What is the purpose of keys in React lists?

A

Keys help React identify which items changed, were added, or removed. They should be unique among siblings and stable across re-renders. Using index as key is acceptable if list is static, but not recommended for dynamic lists. Keys enable efficient reconciliation.

javascript
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
        </li>
      ))}
    </ul>
  );
}
Q13

Explain React Context API and when to use it.

A

Context provides a way to pass data through the component tree without prop drilling. It consists of createContext, Provider, and useContext. Use it for theme, authentication, language settings, or any data needed by many components. Avoid overusing it as it can make components harder to test.

javascript
const ThemeContext = createContext('light');

function App() {
  const [theme, setTheme] = useState('dark');
  
  return (
    <ThemeContext.Provider value={theme}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div className={theme}>Toolbar</div>;
}
Q14

What is useReducer and when should you use it instead of useState?

A

useReducer is a hook for managing complex state logic. It takes a reducer function and initial state, returns current state and dispatch function. Use it when state logic is complex, state updates depend on previous state, or you need to manage multiple related state values together.

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

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  
  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}
Q15

What is useMemo and how does it optimize performance?

A

useMemo memoizes expensive computations. It returns a memoized value that only recalculates when dependencies change. This prevents unnecessary recalculations on every render, improving performance for expensive operations like filtering large arrays or complex calculations.

javascript
function ExpensiveComponent({ items, filter }) {
  const filteredItems = useMemo(() => {
    return items.filter(item => item.category === filter);
  }, [items, filter]);
  
  return (
    <ul>
      {filteredItems.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}
Q16

What is useCallback and why is it important?

A

useCallback returns a memoized callback function that only changes when dependencies change. It prevents child components from re-rendering unnecessarily when passed as props. Essential for optimizing components that receive callback props, especially with React.memo.

javascript
function Parent({ items }) {
  const [count, setCount] = useState(0);
  
  const handleClick = useCallback((id) => {
    console.log('Item clicked:', id);
  }, []);
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
      <ChildList items={items} onItemClick={handleClick} />
    </div>
  );
}

const ChildList = React.memo(({ items, onItemClick }) => {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id} onClick={() => onItemClick(item.id)}>
          {item.name}
        </li>
      ))}
    </ul>
  );
});
Q17

How do you create custom hooks in React?

A

Custom hooks are JavaScript functions starting with "use" that can call other hooks. They allow extracting component logic into reusable functions. Custom hooks share stateful logic between components without changing component hierarchy.

javascript
function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  
  const increment = () => setCount(c => c + 1);
  const decrement = () => setCount(c => c - 1);
  const reset = () => setCount(initialValue);
  
  return { count, increment, decrement, reset };
}

function Counter() {
  const { count, increment, decrement } = useCounter(10);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}
Q18

What are React Error Boundaries?

A

Error boundaries are React components that catch JavaScript errors in child component tree, log them, and display fallback UI. They catch errors during rendering, lifecycle methods, and constructors. They do not catch errors in event handlers, async code, or during server-side rendering.

javascript
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, errorInfo) {
    console.error('Error caught:', error, errorInfo);
  }
  
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    
    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <MyComponent />
    </ErrorBoundary>
  );
}
Q19

What is React.memo and how does it work?

A

React.memo is a higher-order component that memoizes functional components. It prevents re-rendering if props haven't changed by doing a shallow comparison. It only checks prop changes, not state or context changes. Useful for expensive components that receive stable props.

javascript
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
  return (
    <div>
      {data.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}, (prevProps, nextProps) => {
  return prevProps.data.length === nextProps.data.length;
});
Q20

Explain the difference between useRef and useState.

A

useRef returns a mutable object that persists across renders without causing re-renders. useState triggers re-renders when updated. useRef is used for accessing DOM elements, storing previous values, or mutable values that don't need to trigger renders. useState is for state that affects rendering.

javascript
function Component() {
  const [count, setCount] = useState(0);
  const inputRef = useRef();
  const prevCountRef = useRef();
  
  useEffect(() => {
    prevCountRef.current = count;
  });
  
  const focusInput = () => {
    inputRef.current.focus();
  };
  
  return (
    <div>
      <input ref={inputRef} />
      <p>Current: {count}, Previous: {prevCountRef.current}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
Q21

What is prop drilling and how can you avoid it?

A

Prop drilling is passing props through multiple component levels even when intermediate components don't use them. Solutions include Context API for shared data, component composition, state management libraries like Redux, or lifting state up to a common ancestor that needs it.

Q22

How do you handle forms in React?

A

Forms can be controlled (state-managed) or uncontrolled (ref-based). Controlled forms use value and onChange for each input, storing data in state. Form validation can be done with libraries like Formik or React Hook Form, or custom validation logic.

javascript
function LoginForm() {
  const [formData, setFormData] = useState({
    email: '',
    password: ''
  });
  const [errors, setErrors] = useState({});
  
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };
  
  const handleSubmit = (e) => {
    e.preventDefault();
    const newErrors = {};
    
    if (!formData.email) newErrors.email = 'Email required';
    if (!formData.password) newErrors.password = 'Password required';
    
    if (Object.keys(newErrors).length === 0) {
      console.log('Form submitted:', formData);
    } else {
      setErrors(newErrors);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input
        name="email"
        value={formData.email}
        onChange={handleChange}
      />
      {errors.email && <span>{errors.email}</span>}
      <input
        name="password"
        type="password"
        value={formData.password}
        onChange={handleChange}
      />
      {errors.password && <span>{errors.password}</span>}
      <button type="submit">Submit</button>
    </form>
  );
}
Q23

What is code splitting in React and how do you implement it?

A

Code splitting divides your bundle into smaller chunks loaded on demand, reducing initial load time. Implement using React.lazy() for component-level splitting, dynamic imports, or route-based splitting with React Router. Suspense component shows fallback while loading.

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

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

const routes = [
  {
    path: '/dashboard',
    component: React.lazy(() => import('./Dashboard'))
  }
];
Q24

What are Higher-Order Components (HOCs)?

A

HOCs are functions that take a component and return a new component with additional props or behavior. They enable code reuse, logic abstraction, and prop manipulation. Common use cases include authentication, logging, and data fetching. Hooks are now preferred for most use cases.

javascript
function withAuth(WrappedComponent) {
  return function AuthenticatedComponent(props) {
    const [isAuthenticated, setIsAuthenticated] = useState(false);
    
    useEffect(() => {
      checkAuth().then(setIsAuthenticated);
    }, []);
    
    if (!isAuthenticated) {
      return <div>Please log in</div>;
    }
    
    return <WrappedComponent {...props} />;
  };
}

const ProtectedPage = withAuth(MyPage);
Q25

Explain the concept of lifting state up in React.

A

Lifting state up means moving state from child components to their common parent. This allows sharing state between siblings and ensures single source of truth. The parent manages state and passes it down as props, while children receive callbacks to update it.

javascript
function Parent() {
  const [temperature, setTemperature] = useState(20);
  
  return (
    <div>
      <TemperatureInput
        value={temperature}
        onChange={setTemperature}
        scale="celsius"
      />
      <TemperatureInput
        value={temperature}
        onChange={setTemperature}
        scale="fahrenheit"
      />
    </div>
  );
}

function TemperatureInput({ value, onChange, scale }) {
  return (
    <input
      value={value}
      onChange={(e) => onChange(Number(e.target.value))}
    />
  );
}
Q26

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

A

PureComponent implements shouldComponentUpdate with shallow prop and state comparison, preventing re-renders if props/state haven't changed. Regular Component always re-renders unless shouldComponentUpdate returns false. PureComponent can improve performance but may miss updates if props are objects/arrays that mutate.

javascript
class RegularComponent extends React.Component {
  render() {
    return <div>{this.props.name}</div>;
  }
}

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

How do you optimize React application performance?

A

Performance optimization techniques include: React.memo for component memoization, useMemo for expensive calculations, useCallback for stable function references, code splitting and lazy loading, virtualizing long lists, avoiding inline object/function creation in render, using production build, and profiling with React DevTools.

Q28

What is the purpose of React.Fragment?

A

Fragment allows grouping multiple elements without adding extra DOM nodes. It's useful when you need to return multiple elements but can't wrap them in a div. Short syntax <> </> can be used instead of <Fragment>. Fragments can have keys when mapping lists.

javascript
function Component() {
  return (
    <>
      <h1>Title</h1>
      <p>Description</p>
    </>
  );
}

function List() {
  return (
    <>
      {items.map(item => (
        <React.Fragment key={item.id}>
          <td>{item.name}</td>
          <td>{item.value}</td>
        </React.Fragment>
      ))}
    </>
  );
}
Q29

What are portals in React?

A

Portals provide a way to render children into a DOM node outside the parent component hierarchy. Useful for modals, tooltips, popovers that need to break out of container constraints. Created using ReactDOM.createPortal(child, container).

javascript
function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;
  
  return ReactDOM.createPortal(
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}
Q30

How does React handle conditional rendering?

A

Conditional rendering displays different content based on conditions. Methods include: if/else statements, ternary operators, logical && operator, early returns, and switch statements. Choose based on complexity and readability needs.

javascript
function Component({ user, isLoading }) {
  if (isLoading) {
    return <div>Loading...</div>;
  }
  
  if (!user) {
    return <div>Please log in</div>;
  }
  
  return (
    <div>
      {user.isAdmin && <AdminPanel />}
      {user.age >= 18 ? (
        <AdultContent />
      ) : (
        <ChildContent />
      )}
    </div>
  );
}
Q31

What is the purpose of useImperativeHandle hook?

A

useImperativeHandle customizes the instance value exposed when using ref. It works with forwardRef to expose specific methods or properties to parent components. Use sparingly as it breaks component encapsulation. Prefer declarative approaches when possible.

javascript
const Input = forwardRef((props, ref) => {
  const inputRef = useRef();
  
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    getValue: () => {
      return inputRef.current.value;
    }
  }));
  
  return <input ref={inputRef} {...props} />;
});

function Parent() {
  const inputRef = useRef();
  
  const handleClick = () => {
    inputRef.current.focus();
    console.log(inputRef.current.getValue());
  };
  
  return (
    <div>
      <Input ref={inputRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}
Q32

Explain React Server Components and their benefits.

A

Server Components render on the server and send minimal JavaScript to client. Benefits include zero client bundle size for server components, direct database access, secure API keys, faster initial page load, and better SEO. They work alongside Client Components for interactivity.

Q33

What is the difference between shallow and deep copying in React state?

A

Shallow copy creates a new object but nested objects are still referenced. Deep copy creates completely independent copies. React state updates should use shallow copies with spread operator. For nested objects, you need to spread at each level or use libraries like Immer.

javascript
function Component() {
  const [user, setUser] = useState({
    name: 'John',
    address: { city: 'NYC', zip: '10001' }
  });
  
  const updateCity = (newCity) => {
    setUser(prev => ({
      ...prev,
      address: {
        ...prev.address,
        city: newCity
      }
    }));
  };
  
  return <div>{user.address.city}</div>;
}
Q34

How do you handle async operations in useEffect?

A

Use async functions inside useEffect by defining an async function and calling it, or using .then(). Always handle cleanup for subscriptions or timers. Be careful with dependency arrays to avoid infinite loops. Use AbortController for fetch requests to cancel on unmount.

javascript
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    let cancelled = false;
    
    async function fetchUser() {
      try {
        setLoading(true);
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        
        if (!cancelled) {
          setUser(data);
        }
      } catch (error) {
        if (!cancelled) {
          console.error(error);
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }
    
    fetchUser();
    
    return () => {
      cancelled = true;
    };
  }, [userId]);
  
  if (loading) return <div>Loading...</div>;
  return <div>{user?.name}</div>;
}
Q35

What is React Suspense and how does it work?

A

Suspense lets components wait for something before rendering. It shows fallback UI while waiting. Used with React.lazy for code splitting, data fetching libraries, or any async operation. Suspense boundaries catch loading states and display fallback content.

javascript
function App() {
  return (
    <Suspense fallback={<div>Loading page...</div>}>
      <Router>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/about" element={
            <Suspense fallback={<div>Loading about...</div>}>
              <AboutPage />
            </Suspense>
          } />
        </Routes>
      </Router>
    </Suspense>
  );
}
Q36

What are render props in React?

A

Render props is a pattern where a component receives a function as a prop that returns React elements. The component calls this function with data, allowing sharing logic between components. Alternative to HOCs and hooks for code reuse.

javascript
function MouseTracker({ render }) {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  
  useEffect(() => {
    const handleMouseMove = (e) => {
      setPosition({ x: e.clientX, y: e.clientY });
    };
    
    window.addEventListener('mousemove', handleMouseMove);
    return () => window.removeEventListener('mousemove', handleMouseMove);
  }, []);
  
  return render(position);
}

function App() {
  return (
    <MouseTracker
      render={({ x, y }) => (
        <div>
          Mouse position: {x}, {y}
        </div>
      )}
    />
  );
}
Q37

How do you test React components?

A

Testing React components involves unit tests with Jest and React Testing Library, integration tests, and E2E tests. Test user behavior, not implementation. Use render, screen queries, fireEvent or userEvent, and assertions. Mock external dependencies and test accessibility.

javascript
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('increments count on button click', () => {
  render(<Counter />);
  
  const button = screen.getByText('Increment');
  const count = screen.getByText(/count: 0/i);
  
  fireEvent.click(button);
  
  expect(screen.getByText(/count: 1/i)).toBeInTheDocument();
});
Q38

What is the purpose of useId hook?

A

useId generates unique IDs that are stable across server and client renders. Useful for accessibility attributes like htmlFor and id, or generating unique keys. IDs are unique per component instance and work with SSR without hydration mismatches.

javascript
function Checkbox({ label }) {
  const id = useId();
  
  return (
    <div>
      <input type="checkbox" id={id} />
      <label htmlFor={id}>{label}</label>
    </div>
  );
}

function Form() {
  return (
    <form>
      <Checkbox label="Accept terms" />
      <Checkbox label="Subscribe to newsletter" />
    </form>
  );
}
Q39

Explain the concept of reconciliation in React.

A

Reconciliation is the process React uses to update the DOM. When state changes, React creates a new virtual DOM tree, compares it with previous tree (diffing algorithm), identifies minimal set of changes, and updates only those nodes in real DOM. This makes updates efficient.

Q40

What is the difference between element and component in React?

A

An element is a plain object describing what you want to see on screen. It's immutable and cheap to create. A component is a function or class that returns elements. Components can have state, props, and lifecycle. Elements are what components return.

javascript
const element = <h1>Hello World</h1>;

function Component() {
  return <h1>Hello World</h1>;
}

const componentElement = <Component />;
Q41

How do you handle routing in React applications?

A

React Router is the standard library for routing. It provides BrowserRouter, Routes, Route, Link, useNavigate, useParams hooks. Supports nested routes, route parameters, query strings, programmatic navigation, and route guards. For static sites, use file-based routing with Next.js.

javascript
import { BrowserRouter, Routes, Route, Link, useParams } 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="/users/:id" element={<UserProfile />} />
      </Routes>
    </BrowserRouter>
  );
}

function UserProfile() {
  const { id } = useParams();
  return <div>User ID: {id}</div>;
}
Q42

What is the purpose of useTransition hook?

A

useTransition lets you mark state updates as transitions, making them non-urgent. React can interrupt them for more urgent updates. Returns isPending flag and startTransition function. Useful for keeping UI responsive during expensive updates like filtering large lists.

javascript
function SearchResults({ query }) {
  const [isPending, startTransition] = useTransition();
  const [results, setResults] = useState([]);
  
  useEffect(() => {
    startTransition(() => {
      const filtered = largeList.filter(item =>
        item.name.includes(query)
      );
      setResults(filtered);
    });
  }, [query]);
  
  return (
    <div>
      {isPending && <div>Searching...</div>}
      <ul>
        {results.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}
Q43

What is the difference between useDeferredValue and useTransition?

A

useDeferredValue defers updating a value, keeping previous value while new value loads. useTransition marks state updates as non-urgent. Both help keep UI responsive. useDeferredValue is for values, useTransition is for state update functions.

javascript
function SearchResults({ query }) {
  const deferredQuery = useDeferredValue(query);
  const results = useMemo(() => {
    return largeList.filter(item =>
      item.name.includes(deferredQuery)
    );
  }, [deferredQuery]);
  
  return <div>{results.map(r => <div key={r.id}>{r.name}</div>)}</div>;
}
Q44

How do you optimize React list rendering?

A

Optimize lists by using stable keys, virtualizing long lists with react-window or react-virtualized, avoiding inline functions/objects in map, using React.memo for list items, code splitting, pagination, and lazy loading. For very long lists, consider infinite scroll.

javascript
import { FixedSizeList } from 'react-window';

function VirtualizedList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].name}
    </div>
  );
  
  return (
    <FixedSizeList
      height={600}
      itemCount={items.length}
      itemSize={50}
      width="100%"
    >
      {Row}
    </FixedSizeList>
  );
}
Q45

What is the purpose of useSyncExternalStore hook?

A

useSyncExternalStore lets you subscribe to external data sources like browser APIs, third-party libraries, or global state. It ensures components stay in sync with external stores and handles tearing in concurrent rendering. Used internally by React Redux and similar libraries.

javascript
function useOnlineStatus() {
  return useSyncExternalStore(
    subscribe,
    getSnapshot,
    getServerSnapshot
  );
}

function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}

function getSnapshot() {
  return navigator.onLine;
}

function getServerSnapshot() {
  return true;
}
Q46

Explain the concept of composition in React.

A

Composition is building complex UIs by combining smaller components. Instead of inheritance, React uses composition through props.children, render props, or component props. This makes components reusable, flexible, and easier to maintain. Composition over inheritance is a React principle.

javascript
function Card({ title, children, footer }) {
  return (
    <div className="card">
      <div className="card-header">{title}</div>
      <div className="card-body">{children}</div>
      {footer && <div className="card-footer">{footer}</div>}
    </div>
  );
}

function App() {
  return (
    <Card
      title="User Profile"
      footer={<button>Save</button>}
    >
      <input placeholder="Name" />
      <input placeholder="Email" />
    </Card>
  );
}
Q47

What are the Rules of Hooks?

A

Rules of Hooks: 1) Only call hooks at the top level, not inside loops, conditions, or nested functions. 2) Only call hooks from React functions (functional components or custom hooks). Violating these rules causes bugs because React relies on hook call order to track state.

javascript
function Component({ condition }) {
  const [count, setCount] = useState(0);
  
  if (condition) {
    const [name, setName] = useState('');
  }
  
  useEffect(() => {
    const [data, setData] = useState(null);
  }, []);
  
  return <div>{count}</div>;
}

function CorrectComponent({ condition }) {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');
  const [data, setData] = useState(null);
  
  useEffect(() => {
    fetchData().then(setData);
  }, []);
  
  return <div>{count}</div>;
}
Q48

How do you handle side effects in React?

A

Side effects are handled with useEffect hook. Side effects include data fetching, subscriptions, timers, DOM manipulation, and logging. useEffect runs after render and can return a cleanup function. Use dependency array to control when effects run.

javascript
function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);
  
  useEffect(() => {
    const connection = createConnection(roomId);
    connection.on('message', setMessages);
    connection.connect();
    
    return () => {
      connection.disconnect();
    };
  }, [roomId]);
  
  return <div>{messages.map(m => <div key={m.id}>{m.text}</div>)}</div>;
}
Q49

What is the purpose of useInsertionEffect hook?

A

useInsertionEffect fires synchronously before DOM mutations, allowing you to inject styles into the DOM before layout reads. Useful for CSS-in-JS libraries that need to inject styles. Runs before useLayoutEffect. Use sparingly, only for style injection.

javascript
function useCSS(rule) {
  useInsertionEffect(() => {
    const style = document.createElement('style');
    style.textContent = rule;
    document.head.appendChild(style);
    
    return () => {
      document.head.removeChild(style);
    };
  });
  
  return rule;
}
Q50

How do you implement state management in large React applications?

A

For large applications, use Context API for simple global state, Redux for complex state with time-travel debugging, Zustand for lightweight state management, or React Query for server state. Choose based on complexity: Context for theme/auth, Redux for complex app state, React Query for API data.

javascript
import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0,
  user: null,
  increment: () => set((state) => ({ count: state.count + 1 })),
  setUser: (user) => set({ user }),
}));

function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>{count}</button>;
}