How React Compiler Ends Four Years of Manual Optimization

This article reviews recent React developments—including the React 19.2 release, new Activity and useEffectEvent APIs, the stable 1.0 release of babel‑plugin‑react‑compiler—and explains how automatic compiler‑based optimizations replace manual memo, useCallback, and useMemo patterns, while also covering KeepAlive challenges and code examples.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
How React Compiler Ends Four Years of Manual Optimization

Good Things Keep Coming

React has left Facebook and formed a foundation (previously overtaken by Vercel/NestJS, with updates that added little developer value).

React 19.2 introduces new features such as Activity, useEffectEvent, and built‑in KeepAlive.

React Compiler 1.0 stable release promises "no more manual memo".

Good things indeed.

Those Years of React Pain

From React Forget to babel‑plugin‑react‑compiler, four years of waiting finally yields results.

At React Conf 2021, the team showcased "React Forget", a project aimed at solving performance headaches.

Four years later, the babel-plugin-react-compiler 1.0 stable version arrives, ending the long wait.

React's "Stupidity": Why We Need Manual Optimization?

Those "messy" codebases we wrote

In React, every change to state or props triggers a tree‑wide diff, causing many unnecessary re‑renders.

To avoid this, developers litter their code with memo wrappers:

const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
  const processedData = useMemo(() => {
    return data.map(item => ({
      ...item,
      processed: expensiveCalculation(item)
    }));
  }, [data]);

  const handleClick = useCallback(() => {
    onUpdate(processedData);
  }, [processedData, onUpdate]);

  return (
    <div onClick={handleClick}>
      {processedData.map(item => (
        <Item key={item.id} data={item} />
      ))}
    </div>
  );
});

Vue's "Elegance": Fine‑grained reactive updates

Vue achieves automatic, fine‑grained updates without manual memoization:

<template>
  <div @click="handleClick">
    <Item v-for="item in processedData" :key="item.id" :data="item" />
  </div>
</template>

<script setup>
const processedData = computed(() => {
  return data.value.map(item => ({
    ...item,
    processed: expensiveCalculation(item)
  }));
});

const handleClick = () => {
  onUpdate(processedData.value);
};
</script>

Vue's reactivity tracks data changes and updates only affected components, resulting in cleaner and more efficient code.

React Compiler: Four Years of Waiting Finally Pay Off

From React Forget to babel‑plugin‑react‑compiler

In 2021, React Forget aimed to let a compiler automatically optimise component rendering, removing the need for manual React.memo, useCallback, and useMemo code.

After four years of refinement, the technology is now released as the babel-plugin-react-compiler stable 1.0.

Reference: react.dev/learn/react… [1]

npm package: www.npmjs.com/package/babel-plugin-react-compiler [2]

image.png
image.png

Automated Performance Optimisation

The React Compiler performs static analysis at build time and automatically injects necessary optimisations into components.

Example source code:

import { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="h-screen w-screen flex justify-center items-center flex-col gap-8">
      <Comp1 />
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <p>{count}</p>
      <Comp2 />
    </div>
  );
}

function Comp1() {
  return <div className>Comp1 {Math.random()}</div>;
}

function Comp2() {
  return <div className>Comp2 {Math.random()}</div>;
}

After enabling "React Compiler" in Vite, the bundled output shows automatic optimisation without any code changes.

image.png
image.png

With the compiler disabled, the bundle looks different.

image.png
image.png

KeepAlive Before React 19.2

Previously, implementing component state preservation (KeepAlive) was difficult.

Many developers tried to solve it with display: none, which fails to address rendering, DOM size, lifecycle, and performance issues.

My earlier solution combined Suspense with manual component unmounting, resulting in complex code:

import type { KeepAliveProps } from './type';
import { memo, Suspense, use } from 'react';
import { KeepAliveContext } from './context';

const Wrapper = memo<KeepAliveProps>(({ children, active }) => {
  const resolveRef = useRef<Function | null>(null);
  if (active) {
    resolveRef.current?.();
    resolveRef.current = null;
  } else {
    throw new Promise(resolve => {
      resolveRef.current = resolve;
    });
  }
  return children;
});

/** KeepAlive component using Suspense */
export const KeepAlive = memo(({ uniqueKey: key, active, children }: KeepAliveProps & { uniqueKey?: keyof any }) => {
  const { findEffect } = use(KeepAliveContext);
  useEffect(() => {
    const { activeEffect, deactiveEffect } = findEffect(key);
    if (active) {
      activeEffect.forEach(fn => fn());
    } else {
      deactiveEffect.forEach(fn => fn());
    }
  }, [active, findEffect, key]);

  return (
    <Suspense fallback={null}>
      <Wrapper active={active}>{children}</Wrapper>
    </Suspense>
  );
});

Things Got Better

After four years, the React Compiler finally brings automated performance optimisation, and React 19.2 adds useful features, ending the era of "SHIT SSR".

Although React once required many manual optimisations and Vue's reactivity felt more elegant, the new compiler simplifies development, reduces bugs, and lets developers focus on business logic.

frontendReActKeepaliveReact Compiler
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.