React - Key Preparation Guide for Front-End Developer Interviews

Introduction

For developers, job transitions are a standard part of career growth, whether for personal development or other reasons. Ideally, job-hopping should be as frictionless as possible. To assist with preparation, I've compiled a series of A-to-Z guides, starting with React.

Technical Interview Guide - React Edition

Why doesn’t React Hooks support asynchronous promises in callback functions?

The core reason is that React’s rendering and state updates need to remain synchronous. Asynchronous operations can disrupt React’s rendering and state management flow, leading to side effects and unpredictable behavior.

React performs batched updates, a topic we'll discuss later. If state updates occur asynchronously, it can interfere with React’s internal batch optimization. For example, React updates the virtual DOM with new values and reflects changes on the actual DOM as needed. When processed asynchronously, this could cause unnecessary renders or missed updates.

Thus, asynchronous operations are best handled within useEffect:

useEffect(() => {
  const fetchData = async () => {
    const result = await someAPICall();
    setData(result);
  };

  fetchData();
}, []);

In this pattern, the async callback operates independently of React's state and rendering flow, preventing disruption. In summary, React Hooks don't directly support async functions in callbacks to keep state updates and rendering predictable and synchronized.

Is the setState function asynchronous or synchronous?

The setState function often operates asynchronously. This might cause confusion, but it’s different from JavaScript's async tasks (e.g., Promises, async/await). React applies batching for performance, grouping multiple state updates to minimize re-renders, such as when:

  • setState is called within event handlers
  • It’s triggered within lifecycle methods or function components

Consider this example:

function handleClick() {
  setState(prev => prev + 1);
  setState(prev => prev + 1);
}

Here, even though setState is called twice, React batches the updates, causing the final state to increment by 1 instead of 2.

setState timing isn’t guaranteed (unlike true JavaScript async), as React decides the optimal update timing. This is why setState can seem asynchronous.

What is Batching in React?

React optimizes performance by batching multiple state updates into a single re-render, avoiding redundant renders and enhancing performance.

The asynchronous nature of setState isn't due to Promises or async/await, but rather due to React's internal batching mechanism. To execute code after setState, use either the callback function or useEffect to ensure it runs after the state update.

Batch updates usually occur within the event loop and rely on React Fiber and Transactions.

Why did React adopt a functional paradigm?

React embraces the functional paradigm for several reasons: predictability, immutability, and structural simplicity—all of which help manage complex UI states more effectively.

  • Predictability with Pure Functions
      • Functional programming emphasizes pure functions, which provide consistent outputs given the same inputs and don’t alter external state.
      • React components act like pure functions, rendering the same UI based on given props, reducing bugs and simplifying debugging.
  • Immutability
      • Functional programming values immutability, meaning data doesn’t change, and updates create new data objects instead.
      • Immutability aids in state management and performance optimization, helping track changes and minimizing bugs.
  • Declarative Programming
      • React’s declarative approach focuses on "what" the UI should look like based on state, rather than "how" to achieve it.
      • Unlike imperative programming, where UI changes are manually managed, React handles UI updates automatically, reducing complexity.

React’s functional paradigm not only keeps code simple but also ensures that state updates and renderings remain safe and predictable.

(Optional) Difference Between Declarative and Imperative Programming in React

  • Declarative: Declares the result based on the UI state. React automatically updates the UI when the state changes.
  • Imperative: Manages the process of updating the UI step-by-step, directly controlling DOM updates for each state change.

Example of Declarative UI with React:

import { useState } from "react";

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Here, React handles UI changes automatically based on state. We only care that React rerenders when count updates.

(Optional) Time-Travel Debugging with React

Time-Travel Debugging allows you to move backward or forward through application states, helpful for frameworks like React. By logging each state change, you can rewind or reapply state transitions to debug the app. For example, Redux DevTools implements this for React-Redux applications.

How does the Virtual DOM work?

React’s Virtual DOM is a lightweight, virtual copy of the actual DOM that allows for efficient DOM updates. When state or props change, React creates a new Virtual DOM tree and compares it to the previous one, identifying minimal changes (diffing) to update the actual DOM.

Virtual DOM Lifecycle:

  • Initial Render: JSX is converted into a Virtual DOM tree that reflects the actual DOM in memory.
  • State or Props Change: A new Virtual DOM is created based on the updated state.
  • Diffing: React compares the new and previous Virtual DOMs, identifying differences via its Diffing Algorithm.
  • Patching: React updates the actual DOM only with the changed elements.

This approach minimizes expensive DOM manipulations, resulting in efficient updates.

Example Structure of Virtual DOM:

{
  type: 'div',
  props: { id: 'app', className: 'container' },
  children: [
    { type: 'h1', props: { style: 'color: red;' }, children: ['Hello, World!'] },
    { type: 'button', props: { onClick: () => console.log('Clicked!') }, children: ['Click me'] }
  ]
}

Benefits of Virtual DOM:

  • Minimal DOM Manipulation: Reduces re-render costs by targeting specific changes.
  • Performance Optimization: Only the necessary parts of the DOM are updated, improving efficiency.

React’s Virtual DOM, combined with its diffing algorithm, optimizes UI updates, making complex applications responsive and performant.

← Go home