How React Works Under the Hood

React is a powerful JavaScript library for building user interfaces, but understanding how it works internally can help you write better, more performant applications. This document explains the core mechanisms that make React efficient and powerful.

The React Workflow Overview

React follows a systematic workflow that transforms your JSX code into actual DOM updates:

  1. JSX → 2. React.createElement → 3. Virtual DOM → 4. Diffing → 5. Real DOM

Let's dive deep into each step of this process.

1. JSX (JavaScript XML)

JSX is a syntax extension for JavaScript that allows you to write HTML-like code within your JavaScript files. While it looks like HTML, JSX is actually syntactic sugar that gets transformed into JavaScript function calls.

What JSX Looks Like:

const element = <h1 className='greeting'>Hello, World!</h1>;

Key Points:

2. React.createElement

During the build process, JSX gets transformed into React.createElement() function calls. This is the bridge between your declarative JSX and React's internal representation.

Transformation Example:

// JSX
const element = <h1 className='greeting'>Hello, World!</h1>;

// Becomes this JavaScript:
const element = React.createElement(
  'h1', // type
  { className: 'greeting' }, // props
  'Hello, World!' // children
);

React.createElement Signature:

React.createElement(type, props, ...children);

What createElement Returns:

It returns a plain JavaScript object called a "React element":

{
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, World!'
  },
  key: null,
  ref: null,
  $$typeof: Symbol(react.element)
}

3. Virtual DOM

The Virtual DOM is React's secret weapon for performance. It's a lightweight, in-memory representation of the actual DOM, stored as a tree of JavaScript objects.

What is the Virtual DOM?

Virtual DOM Structure:

// Virtual DOM representation of <div><h1>Title</h1><p>Content</p></div>
{
  type: 'div',
  props: {
    children: [
      {
        type: 'h1',
        props: { children: 'Title' }
      },
      {
        type: 'p',
        props: { children: 'Content' }
      }
    ]
  }
}

Benefits of Virtual DOM:

  1. Performance: Batches DOM updates and minimizes expensive DOM operations
  2. Predictability: Makes UI updates more predictable and easier to debug
  3. Declarative: Allows you to describe what the UI should look like, not how to change it

4. Diffing Algorithm

The diffing algorithm is React's process for determining what changes need to be made to the real DOM. It compares the new Virtual DOM tree with the previous Virtual DOM tree.

How Diffing Works:

1. Tree Comparison

React compares trees level by level, starting from the root:

2. Component Comparison

When comparing components:

3. Child Element Comparison

React uses keys to efficiently handle lists of children:

// Without keys (inefficient)
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>

// With keys (efficient)
<ul>
  <li key="1">Item 1</li>
  <li key="2">Item 2</li>
</ul>

Diffing Optimizations:

  1. Heuristic Algorithm: React uses heuristics that work well for most use cases
  2. Key Prop: Uses keys to identify which items have changed, added, or removed
  3. Component Boundaries: Limits diffing scope to component boundaries

Reconciliation Process:

  1. Element Type Check: Compare element types first
  2. Props Comparison: If types match, compare props
  3. Children Recursion: Recursively apply the same process to children
  4. Update Queue: Build a list of necessary DOM operations

5. Real DOM Updates

After diffing determines what needs to change, React updates the actual DOM with minimal operations.

DOM Update Process:

1. Commit Phase

React applies all the changes calculated during the diffing phase:

2. Batching Updates

React batches multiple state updates together for performance:

// These will be batched together
setState({ count: count + 1 });
setState({ name: 'New Name' });
setState({ active: true });

3. Effect Execution

After DOM updates, React runs effects (useEffect, componentDidMount, etc.)

Performance Benefits:

  1. Minimal DOM Manipulation: Only updates what actually changed
  2. Batched Updates: Groups multiple changes into single DOM operations
  3. Asynchronous Updates: Updates happen asynchronously when possible

React Fiber Architecture (React 16)

Modern React uses Fiber architecture to make this process even more efficient:

What is Fiber?

Key Fiber Features:

  1. Time Slicing: Breaks work into small chunks
  2. Prioritization: High-priority updates (user input) interrupt low-priority ones
  3. Suspense: Enables components to "wait" for something before rendering
  4. Concurrent Features: Enables concurrent rendering capabilities

Best Practices for Performance

Understanding React's internals helps you write more performant code:

1. Use Keys Properly

// Good: Stable, unique keys
{
  items.map((item) => <Item key={item.id} data={item} />);
}

// Bad: Array indices as keys
{
  items.map((item, index) => <Item key={index} data={item} />);
}

2. Minimize Re-renders

// Use React.memo for functional components
const ExpensiveComponent = React.memo(({ data }) => {
  return <div>{/* Complex rendering */}</div>;
});

// Use useMemo for expensive calculations
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(props.data);
}, [props.data]);

3. Keep Components Small

4. Avoid Inline Objects and Functions

// Bad: Creates new object on every render
<Component style={{ marginTop: 10 }} />;

// Good: Define outside render or use useMemo
const styles = { marginTop: 10 };
<Component style={styles} />;

Conclusion

React's under-the-hood workflow is a sophisticated system designed for performance and developer experience:

  1. JSX provides a declarative way to describe UI
  2. React.createElement transforms JSX into JavaScript objects
  3. Virtual DOM creates an efficient in-memory representation
  4. Diffing determines the minimal set of changes needed
  5. Real DOM updates apply only the necessary changes

Understanding this process helps you:

The beauty of React is that while this complex process happens under the hood, you can focus on writing declarative, component-based UI code while React handles the efficient updates for you.