React 19 and Its Optimization Improvements via the New Compiler

What is the optimization in react: Typically optimization in react refers to improve the user experience by reducing the load time and minimizing the unnecessary re-rendering in the DOM. Developers have handled optimization manually by applying techniques like lazy loading , React.memo and using optimization hooks such as useMemo and useCallBack. Before diving into the new feature of React compiler presented in react 19 version, let us understand the techniques developers have been using to improve performance and optimization. 1. Performance Hooks: - UseMemo : In JavaScript, objects and arrays are passed by reference. This means that during a re-render, even if their content doesn't change, a new reference is created. In the context of react , re-rendering will create new reference for the object/array, so we need to cache the result of a calculation between re-renders. UseMemo come to address this issue and returns a memoized value. let us understand by the example below when a user object will be memoized and will refer to a new reference only when one of its dependencies changes. import React, { useState, useMemo } from "react"; const UserProfile = () => { const [username, setUsername] = useState(""); const [age, setAge] = useState(20); // user object is stable unless username or age changes const user = useMemo(() => { return { name: username, age: age, }; }, [username, age]); return ( setUsername(e.target.value)} /> {user.name} is {user.age} years old ); }; -useCallBack: The useCallback is similar to useMemo Hooks. The main difference is that useCallback returns a memoized function instead of memoized value. let's understand the example below from w3school.com without useCallbackat each time countchange Appcomponent re-rendering so a new reference of addTodofunction will be created and then Todoscomponent will be re-rendered (as addTodo one of its props). import { useState, useCallback } from "react"; import ReactDOM from "react-dom/client"; import Todos from "./Todos"; const App = () => { const [count, setCount] = useState(0); const [todos, setTodos] = useState([]); const increment = () => { setCount((c) => c + 1); }; const addTodo = useCallback(() => { setTodos((t) => [...t, "New Todo"]); }, [todos]); return ( Count: {count} + ); }; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); //Todo component import { memo } from "react"; const Todos = ({ todos, addTodo }) => { console.log("child render"); return ( My Todos {todos.map((todo, index) => { return {todo}; })} Add Todo ); }; export default memo(Todos); 2. React memo: By default a child component will be re-rendered if its parent component re-renders , using memo will cause React to skip rendering a component if its props have not changed. The example used in useCallBack example already used React.memo to avoid re-rendering when count state changed (countstate will only cause re-rendering in the Appcomponent , not in the child component Todos. 3. Lazy loading: It is used for code splitting , in React, it is a technique that allows you to load components, modules, or assets asynchronously, improving the loading time of your application. It can be achieved by using the built-in React.lazy() method and Suspense component. the example below show the way to implement it ,Loadingcomponent here is the UI to display when the loading is processing , it could be simply ....Loading import { lazy, Suspense } from 'react'; const MarkdownPreview = lazy(() => import('./MarkdownPreview')); function App() { return ( Preview ); } 4. React 19: the react compiler RC: So now as we are familiar with the manual way of fixing optimization and implementing the necessary techniques that address it. The react compiler presented in the 19th version comes essentially to enhance the performance and optimization without the intervention of developers. And as it states its documentation that it’s easy to forget applying memoization or applying them incorrectly can lead to inefficient updates as React has to check parts of your UI that don’t have any meaningful changes. The compiler uses its knowledge of JavaScript and React’s rules to automatically memoize values or groups of values within your components and hooks. Conclusion: Should we handle optimization manually ? short answer, No, React compiler will do it for us. Is still worth to understand techniques of optimization in react? *Yes * it worths as majoriy of projects and apps used by companies still need the manual way, in addition, according to react documentation RC isn't stable yet even it was tested by Meta in production.

May 2, 2025 - 18:51
 0
React 19 and Its Optimization Improvements via the New Compiler

What is the optimization in react:

Typically optimization in react refers to improve the user experience by reducing the load time and minimizing the unnecessary re-rendering in the DOM.
Developers have handled optimization manually by applying techniques
like lazy loading , React.memo and using optimization hooks such as useMemo and useCallBack.
Before diving into the new feature of React compiler presented in react 19 version, let us understand the techniques developers have been using to improve performance and optimization.

1. Performance Hooks:

- UseMemo :

In JavaScript, objects and arrays are passed by reference. This means that during a re-render, even if their content doesn't change, a new reference is created.
In the context of react , re-rendering will create new reference for the object/array, so we need to cache the result of a calculation between re-renders.
UseMemo come to address this issue and returns a memoized value.
let us understand by the example below when a user object will be memoized and will refer to a new reference only when one of its dependencies changes.


import React, { useState, useMemo } from "react";

const UserProfile = () => {
  const [username, setUsername] = useState("");
  const [age, setAge] = useState(20);

  // user object is stable unless username or age changes
  const user = useMemo(() => {
    return {
      name: username,
      age: age,
    };
  }, [username, age]);

  return (
    <div>
      <input
        placeholder="Enter name"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <p>{user.name} is {user.age} years old</p>
    </div>
  );
};

-useCallBack:

The useCallback is similar to useMemo Hooks. The main difference is that useCallback returns a memoized function instead of memoized value.
let's understand the example below from w3school.com
without useCallbackat each time countchange Appcomponent re-rendering so a new reference of addTodofunction will be created and then Todoscomponent will be re-rendered (as addTodo one of its props).

import { useState, useCallback } from "react";
import ReactDOM from "react-dom/client";
import Todos from "./Todos";

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = useCallback(() => {
    setTodos((t) => [...t, "New Todo"]);
  }, [todos]);

  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
//Todo component
import { memo } from "react";

const Todos = ({ todos, addTodo }) => {
  console.log("child render");
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};

export default memo(Todos);

2. React memo:

By default a child component will be re-rendered if its parent component re-renders , using memo will cause React to skip rendering a component if its props have not changed.
The example used in useCallBack example already used React.memo
to avoid re-rendering when count state changed (countstate will only cause re-rendering in the Appcomponent , not in the child component Todos.

3. Lazy loading:

It is used for code splitting , in React, it is a technique that allows you to load components, modules, or assets asynchronously, improving the loading time of your application. It can be achieved by using the built-in React.lazy() method and Suspense component.
the example below show the way to implement it ,Loadingcomponent here is the UI to display when the loading is processing , it could be simply

<p>....Loading<p>
import { lazy, Suspense } from 'react';

const MarkdownPreview = lazy(() => import('./MarkdownPreview'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <h2>Preview</h2>
      <MarkdownPreview /> 
    </Suspense>
  );
}


4. React 19: the react compiler RC:

So now as we are familiar with the manual way of fixing optimization and implementing the necessary techniques that address it.
The react compiler presented in the 19th version comes essentially to enhance the performance and optimization without the intervention of developers.
And as it states its documentation that it’s easy to forget applying memoization or applying them incorrectly can lead to inefficient updates as React has to check parts of your UI that don’t have any meaningful changes.
The compiler uses its knowledge of JavaScript and React’s rules to automatically memoize values or groups of values within your components and hooks.

Conclusion:

Should we handle optimization manually ? short answer, No, React compiler will do it for us.
Is still worth to understand techniques of optimization in react?
*Yes * it worths as majoriy of projects and apps used by companies still need the manual way, in addition, according to react documentation RC isn't stable yet even it was tested by Meta in production.