React is React, just.
Part 2

February 24, 2026

Note: I am neither affiliated with Meta nor involved in React Compiler development. This article is purely based on observations from the outside.

In the previous article, I discussed whether React Components are no longer "Just JavaScript" with the introduction of React Compiler. This time, as a continuation, I'll take a broader look at Meta's ecosystem and explore more deeply how React is evolving as a "language."

Meta and JavaScript Infrastructure

Meta (formerly Facebook) has made significant contributions to the JavaScript ecosystem over the years.

Babel

Babel is a JavaScript transpiler that originally started as 6to5. It transforms ES6+ and JSX syntax that browsers don't natively support, maintaining backward compatibility.

JSX was created as an extension to ECMAScript with the purpose of designing a more concise and easy-to-understand syntax for building DOM tree structures and attributes. — The Role of Babel in React

Babel is an independent open-source project, but it's an essential part of the React ecosystem. And React Compiler is also implemented as a Babel Plugin.

Flow

Flow is a static type checker for JavaScript developed by Meta. Flow is also implemented as a Babel Plugin (@babel/preset-flow), stripping type annotations and custom syntax at runtime. And as one of today's main topics, Flow is extending beyond a type checker to become a "language."

Flow's Component Syntax and Hook Syntax

In April 2024, the Flow team announced Component Syntax. This provides first-class language support for React primitives like components and hooks.

Why Was It Added?

Component Syntax was designed in coordination with the React team, and is already being used across Meta's codebases. — New Flow Language Features for React

These features bring improved ergonomics, expressiveness, and static enforcement for many of the Rules of React. — Flow Blog

In other words, Flow's Component Syntax was designed in coordination with the React team and aims to statically enforce the Rules of React.

Component Syntax

Instead of regular function components, you define them using the component keyword:

// Traditional function component
function Introduction(props: { name: string, age: number }) {
  return <h1>My name is {props.name} and I am {props.age} years old</h1>
}

// Flow's Component Syntax
component Introduction(name: string, age: number) {
  return <h1>My name is {name} and I am {age} years old</h1>
}

Reference: Component Syntax | Flow

With Component Syntax:

  • Props become direct parameters: Reduced boilerplate
  • Automatic ref handling: Internally wrapped with React.forwardRef
  • Explicit return required: All branches must have a return
  • this is forbidden: Cannot use this inside components

Hook Syntax

Similarly, you define hooks using the hook keyword:

// Traditional custom hook
function useOnlineStatus(initial: boolean): boolean {
  const [isOnline, setIsOnline] = useState(initial);
  // ...
  return isOnline;
}

// Flow's Hook Syntax
hook useOnlineStatus(initial: boolean): boolean {
  const [isOnline, setIsOnline] = useState(initial);
  // ...
  return isOnline;
}

Reference: Hook Syntax | Flow

What Flow Detects

Flow's Component/Hook Syntax statically detects code that violates the Rules of React:

  1. Props mutation detection: Code that tries to mutate props inside a component
  2. Conditional hook call prevention: Reports hook calls inside if statements as errors
  3. Ref access during render detection: Code that reads or writes refs during render
  4. Nested component/hook detection: Defining another component/hook inside a component or hook

Flow is able to detect mutations of props in a component or hook. Another pattern enforced in component bodies is that refs are not read or written to during render. — Flow Documentation

What This Means

Flow's Component Syntax and Hook Syntax are an attempt to explicitly define React as a "language."

Previously, React components were defined as "JavaScript functions." However, by introducing new keywords (component, hook), Flow expresses React's semantics at the language level.

This more clearly demonstrates the conclusion from the previous article: "React is React."

React Compiler: The Implicit Approach

While Flow "explicitly" introduces new syntax, React Compiler takes an "implicit" approach.

History of React Compiler

React Compiler is the result of about 10 years of research:

  • 2017: Facebook first explored compilers with Prepack
  • 2021: Xuan Huang demoed the first iteration of the new approach
  • 2024: Beta release, announced at React Conf 2024
  • October 2025: React Compiler v1.0 stable release

Reference: React Compiler v1.0 – React

Hooks: The Moment React Was Defined as a "Language"

Here I want to present an important perspective.

React was defined as a "language" at the moment Hooks were introduced.

Hooks have Rules of Hooks, constraints that don't exist in JavaScript:

  • Only call at the top level (not in loops, conditions, or nested functions)
  • Only call from React functions (not from regular JavaScript functions)

These are rules that don't exist for JavaScript functions. Functions that use Hooks are no longer "JavaScript functions" but "React functions."

In other words, the introduction of Hooks may have been the moment that defined React as a "language" with its own semantics.

Hooks Design and the Compiler

And Hooks were designed from the beginning with compiler optimization in mind.

The React Compiler v1.0 blog states:

Hooks were designed with a future compiler in mind. — React Compiler v1.0

This isn't an afterthought. The official Hooks documentation published in 2018 already stated this intention:

As Svelte, Angular, Glimmer, and others show, ahead-of-time compilation of components has a lot of future potential. Especially if it's not limited to templates.

Introducing Hooks – React (2018)

We wanted to present an API that makes it more likely for code to stay on the optimizable path. To solve these problems, Hooks let you use more of React's features without classes.

Introducing Hooks – React (2018)

In other words, Hooks were designed from the beginning with compiler optimization in mind.

Dan Abramov's Statements

Dan Abramov, who was on the React team at the time, also mentioned automatic memoization by compilers early on.

In the article "Before You memo()" published in February 2021, after discussing the hassle of manual memoization, he stated:

This last step is annoying, especially for components in between, and ideally a compiler would do it for you. In the future, it might.

— Dan Abramov, Before You memo() (2021)

"In the future, a compiler might do this automatically"—this statement was made more than 3 years before React Compiler was publicly released.

The React team had a clear vision of automatic optimization by compilers for many years. This shows that React's evolution from "Just JavaScript" to "a language with its own semantics" was a planned process.

What React Compiler Does

As mentioned in the previous article, React Compiler automatically performs optimizations like this:

// Input
function VideoTag({ heading, videos, filter }) {
  const filteredVideos = [];
  for (const video of videos) {
    if (applyFilter(video, filter)) {
      filteredVideos.push(video);
    }
  }
  // ...
}
// Output (after compilation)
function VideoTab(t36) {
  const $ = useMemoCache(12);
  const { heading, videos, filter } = t36;
  let filteredVideos;

  if ($[0] !== videos || $[1] !== filter) {
    filteredVideos = [];
    for (const video of videos) {
      if (applyFilter(video, filter)) {
        filteredVideos.push(video);
      }
    }
    $[0] = videos;
    $[1] = filter;
    $[2] = filteredVideos;
  } else {
    filteredVideos = $[2];
  }
  // ...
}

Reference: Understanding Idiomatic React – Joe Savona, Mofei Zhang, React Advanced 2023

Conditional Memoization: What useMemo Can't Do

The React Compiler v1.0 blog shows examples of optimizations that manual useMemo/useCallback cannot achieve:

export default function ThemeProvider(props) {
  if (!props.children) {
    return null;
  }
  // The compiler can memoize code after conditional returns
  // (impossible with manual useMemo/useCallback)
  const theme = mergeTheme(props.theme, use(ThemeContext));
  return (
    <ThemeContext value={theme}>
      {props.children}
    </ThemeContext>
  );
}

This is a compiler-specific capability that cannot be implemented with useMemo/useCallback. — React Compiler v1.0

Static Enforcement of Rules of React

React Compiler includes a pass that validates the Rules of React, and diagnostics are provided through the ESLint plugin:

React Compiler's ESLint plugin helps developers proactively identify and correct Rules of React violations. The team strongly recommends everyone use the linter today. — React Compiler Beta Release

Results at Meta

React Compiler is already running in production at Meta:

  • Instagram: Average 3% improvement across all pages
  • Quest Store: At least 4% improvement in load times, some interactions more than 2x faster, initial loads improved by up to 12%

Reference: React Compiler v1.0

Integration Between React Compiler and Flow

What's important here is that React Compiler explicitly supports Flow's Component/Hook Syntax.

compilationMode Option

React Compiler has a compilationMode option that controls which functions are compiled:

  • 'infer' : Uses component naming conventions (PascalCase) and hook detection (use prefix)
  • 'annotation': Only functions marked with "use memo" directive
  • 'syntax': Only functions using Flow's component/hook syntax
  • 'all': All top-level functions (not recommended)

'syntax' Mode

When using 'syntax' mode, only components and hooks defined with Flow's dedicated syntax are compiled:

// babel.config.js
{
  compilationMode: 'syntax'
}
// ✅ Compiled: Flow component syntax
component Button(label: string) {
  return <button>{label}</button>;
}

// ✅ Compiled: Flow hook syntax
hook useCounter(initial: number) {
  const [count, setCount] = useState(initial);
  return [count, setCount];
}

// ❌ Not compiled: Regular function syntax
function helper(data) {
  return process(data);
}

Reference: compilationMode – React

What This Means

Flow and React Compiler are not separate projects, but designed to work together.

  • Flow's Component Syntax was designed in coordination with the React team
  • React Compiler explicitly supports Flow's syntax
  • Inside Meta, these two are used in combination

In other words, Meta is developing both Flow and React Compiler under a consistent strategy of "defining React as a language."

React Documentation and the function Keyword

Here I want to share an observation.

In React's official documentation, the function keyword is consistently used for component definitions:

export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3Am.jpg"
      alt="Katherine Johnson"
    />
  )
}

Reference: Your First Component – React

There is no mention whatsoever of arrow functions (const Profile = () => {}).

Why Not Arrow Functions?

Dan Abramov stated on overreacted.io:

it doesn't matter whether I use arrows or function declarations — Dan Abramov

Technically, both arrow functions and function declarations work fine as React components. However, there are some considerations as to why the React documentation continues to use the function keyword.

1. Affinity with Flow's Component Syntax

Flow's Component Syntax uses the component keyword:

component Introduction(name: string, age: number) {
  // ...
}

This can be naturally introduced as a replacement for the function keyword. If the React documentation had recommended arrow functions, this transition would be unnatural.

2. Syntactic Consistency

Function declarations with the function keyword can be naturally replaced when transitioning to dedicated syntax (like Flow's Component Syntax) in the future. The transition from function declarations is more syntactically consistent than from arrow functions.

Comparing the Two Approaches

Flow and React Compiler take different approaches to the same problem:

Flow:

  • Method: New keywords (component, hook)
  • Explicitness: Explicit (new syntax)
  • Target: Meta's internal codebases
  • Purpose: Static enforcement of Rules of React

React Compiler:

  • Method: Transforms existing syntax
  • Explicitness: Implicit (transformation)
  • Target: All React users
  • Purpose: Auto-memoization + Rules of React validation

However, both are aligned in the direction that "React has its own semantics."

Rules of React

Let's review the Rules of React:

Rules are guidelines for writing idiomatic, high-quality React code. They're not just guidelines—if you don't follow them, you'll have bugs. — Rules of React – React

Key rules:

  1. Components and Hooks must be Pure

    • Idempotent: Same output for same input
    • Side effects only outside of rendering
    • props, state, Hook return values are immutable
  2. React calls Components and Hooks

    • Don't call component functions directly
    • Don't pass Hooks as regular values
  3. Rules of Hooks

    • Only call at the top level
    • Only call from React functions

These rules form the "React semantics." And both Flow's Component Syntax and React Compiler aim to statically enforce these rules.

Conclusion: React is Evolving as a "Language"

In the previous article, I concluded:

React is React. It's a separate entity with the same syntax as JavaScript but different semantics.

This investigation has reinforced that conclusion:

  1. Flow's Component Syntax explicitly defines React semantics as a language
  2. React Compiler implicitly transforms React semantics into JavaScript
  3. Hooks were designed from the beginning with compilers in mind
  4. React documentation consistently uses the function keyword, possibly preparing for future syntax extensions

The era when React was "Just JavaScript" is gradually coming to an end. React is React—the meaning of these words will become increasingly important.


This is merely my essay and does not represent the official views of the React Team or Meta.

Related

Back to all posts