






Reprenons les bases...
Comment fonctionne le rendering ?
Comment fonctionne le rendering ?





Illustrations par Rachel Lee Nabors
Comment se déclenche un render ?
- Render initial du composant.
- L'état du composant est mis à jour.
- L'état d'un des composants parents est mis à jour.
Comment fonctionne un re-render ?





Illustrations par Rachel Lee Nabors
Qu'est-ce qui est coûteux en performance ?


Illustrations par Rachel Lee Nabors
- L'état d'un des composants parents est mis à jour.
Memoization de composants .
Memoization de composants .
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de composants .
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de composants .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de composants .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de functions .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = useCallback(
(todo) => setTodos(todos => getUpdated(todos, todo)),
[]);
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de functions .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = useCallback(
(todo) => setTodos(todos => getUpdated(todos, todo)),
[]);
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de computed value .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = useCallback(
(todo) => setTodos(todos => getUpdated(todos, todo)),
[]);
const filteredTodos = useMemo(
getFiltered(todos, visibility),
[todos, visibility]
);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Memoization de computed value .
const Todo = React.memo(UnmemoizedTodo);
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = useCallback(
(todo) => setTodos(todos => getUpdated(todos, todo)),
[]);
const filteredTodos = useMemo(
getFiltered(todos, visibility),
[todos, visibility]
);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
Et c'est pour ça que...
Et c'est pour ça que...


Retour en arrière...
2021.
2021.
Annonce du React Compiler
2021.
Annonce de React Forget
2021.
Annonce de React Forget


2021.
Annonce de React Forget
DX | UX | |
---|---|---|
React sans mémoïsation | 😍 | 🤬 |
"Memoïser correctement" "Tout mémoïser" | 🤯 | 😍 |
2021.
Annonce de React Forget
- Un nouveau projet React Labs 🧪
- Un compilateur qui mémoïse automatiquement 🪄
- En supportant toutes les bases de code ⚛️
2022.
2022.
Avancement du React Labs
2022.
Avancement du React Labs

2024.
2024.
React Compiler en
React Canary
2024.
React Compiler en
React Canary







2024.
React Compiler en
Beta

2025.
React Compiler en
Release Candidate

2025.
React Compiler en
Release Candidate



Le React Compiler, au final c'est quoi ?
Le React Compiler, au final c'est quoi ?

Compiler
Un compilateur ?

Compiler
Un compilateur est un programme qui transforme un code source en un
code objet
Un Compiler ou un Transpiler ?

Transpiler
Un Compiler ou un Transpiler ?

Transpiler
Un transpileur est un type de compilateur qui prend le code source
d'un langage de programmation et le compile dans un autre langage de
programmation
Un Compiler ou un Transpiler ?

Compiler

Transpiler
Important ?
Le React Compiler, au final c'est quoi ?

Compiler

Un plugin eslint
Qu'est-ce qu'il fait ?
useMemo

React.memo

useCallback

Qu'est-ce qu'il fait ?
useMemo

React.memo

useCallback

Mémoïser automatiquement des valeurs ou des groupes de valeurs dans les composants et les hooks.
- Éviter le re-rendu en cascade des composants.
- Éviter des calculs coûteux externes à React.
Et c'est pas tout ...
- Mémoriser les dépendances aux effets.
- Étapes d'amélioration du code JSX.
- Amélioration des Devtools.
- ...
Qu'est-ce que ça suppose ?
Qu'est-ce que ça suppose ?

Code JavaScript valide
Qu'est-ce que ça suppose ?

Code JavaScript valide

Toutes les valeurs sont accessibles
Qu'est-ce que ça suppose ?

Code JavaScript valide

Toutes les valeurs sont accessibles

Le code suit les Rules of React
Les Rules of React, qu'est-ce que c'est ?
Les Rules of React, qu'est-ce que c'est ?
react.dev

-
Components and Hooks must be pure
- Vos composants et Hooks doivent être idempotents
- Aucun Side effects pendant un render
- Props et states sont immuables
- ...
Les Rules of React, qu'est-ce que c'est ?
react.dev

-
React calls Components and Hooks
- Ne jamais faire passer les Hooks comme des valeurs régulières
- Ne jamais appeler directement les fonctions des composants
- Ne pas utiliser dynamiquement les Hooks (e.g : props...)
- ...
Les Rules of React, qu'est-ce que c'est ?
react.dev

-
Rules of Hooks
- N'appeler les Hooks qu'au top level (e.g : ❌ conditions, try/catch)
- N'appeler les Hooks qu'à partir des fonctions React
- ...
Et pour vous aider avec ces règles :



📦 eslint-plugin-react
📦 eslint-plugin-react-hooks
Est-ce qu'il faut utiliser React Compiler ?

- Plus besoin de mémoïsation à la main 🧠
- Facile à mettre en place 😎
- Fonctionne avec des versions de React < 19 👨🏼🦳
-
Mise en place sécurisée dans vos bases de code 🛡
- React Compiler peut vérifier le respect des Rules of React, et sautera la compilation en toute sécurité lorsqu'il détectera une erreur ⏭️
Pour résumer ...
Pour résumer ...

Make it easy to build great user experiences

Compilons à la main :
React without memo - Xuan Huang
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
const filteredTodos = getFiltered(todos, visibility);
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
if (hasVisibilityChanged || hasTodosChanged) {
const filteredTodos = getFiltered(todos, visibility);
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = getFiltered(todos, visibility);
} else {
filteredTodos = ????
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange = (todo) => setTodos(todos => getUpdated(todos, todo));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
{jsx_addTodo}
</div>
);
}
✨
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
} else {
filteredTodos = memoCache[1];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return (
<div>
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
{jsx_addTodo}
</div>
);
}
✨
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos, jsx_todos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
jsx_todos = memoCache[2] = (
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
);
} else {
filteredTodos = memoCache[1];
jsx_todos = memoCache[2];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return <div>{jsx_todos}{jsx_addTodo}</div>;
}
✨
✨
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos, jsx_todos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
jsx_todos = memoCache[2] = (
<ul>
{filteredTodos.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
);
} else {
filteredTodos = memoCache[1];
jsx_todos = memoCache[2];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return <div>{jsx_todos}{jsx_addTodo}</div>;
}
✨
✨
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
if (hasVisibilityChanged || hasThemeColorChanged || hasTodosChanged) {
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos, jsx_todos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
jsx_todos = memoCache[2] = (<ul>{filteredTodos.map(...)}</ul>);
} else {
filteredTodos = memoCache[1];
jsx_todos = memoCache[2];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return (memoCache[4] = <div>{jsx_todos}{jsx_addTodo}</div>);
} else {
return memoCache[4];
}
}
✨
✨
✨
✨
✨
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache;
if (hasVisibilityChanged || hasThemeColorChanged || hasTodosChanged) {
const handleChange =
memoCache[0] ||
(memoCache[0] = (todo) => setTodos(todos => getUpdated(todos, todo)));
let filteredTodos, jsx_todos;
if (hasVisibilityChanged || hasTodosChanged) {
filteredTodos = memoCache[1] = getFiltered(todos, visibility);
jsx_todos = memoCache[2] = (<ul>{filteredTodos.map(...)}</ul>);
} else {
filteredTodos = memoCache[1];
jsx_todos = memoCache[2];
}
const jsx_addTodo = hasThemeColorChanged
? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />)
: memoCache[3];
return (memoCache[4] = <div>{jsx_todos}{jsx_addTodo}</div>);
} else {
return memoCache[4];
}
}
✨
✨
✨
✨
✨
React Compiler Playground .
+ 43 étapes au sein du React Compiler .
+ 43 étapes au sein du React Compiler .
- HIR.
Pour faire simple :
43 étapes ➜ 10 grandes catégories ➜ Pourquoi on fait simple ?
Pour faire simple :
Déterminer qu'est-ce qui doit être compilé dans les fichiers, selon notre configuration ou les directives utilisées 📂
Conversion de Babel AST en HIR (High-level Intermediate Representation) 🤯
Processus de normalisation et d'optimisation du HIR 🧹
Vérification des Rules of React, suppression du code mort, inférence de types et localisation des éléments réactifs ✅
Inférence des groupes de valeurs qui peuvent être créés et mutés ainsi que les éléments impliqués dans ces créations / mutations 🔍
Construction des portées réactives et optimisations des portées erronées 🏗️
Conversion et renvoi au plugin Babel 📝
Babel remplace le noeud d'origine par la nouvelle version 🔚
Pourquoi on fait si simple ?
Pourquoi on fait si simple ?

Pourquoi on fait si simple ?

🇫🇷 Traduction 🇫🇷 Expliquez pas ça, c'est pas du tout le but du React Compiler, vous allez faire peur à tout le monde... 😡
Démo time .
Démo time .

Et si on compilait notre application de compilation avec le compiler ? 🤯
Ça tourne en prod ?
Ça tourne en prod ?


Qu'est-ce qu'on peut faire dès maintenant ?
Qu'est-ce qu'on peut faire dès maintenant ?
Et plein d'autres...
Du coup, Easier, Better, Faster, Stronger ?
Le React Compiler ne fait pas :
Le React Compiler ne fait pas :
- Une stratégie de re-rendu parfaite
- Corriger le mauvais code
- Supporter les features legacy (Class Components...)
- Une nouvelle manière d'écrire du React
Le React Compiler fait :
Le React Compiler fait :
- Limite le nombre de re-rendu et améliore les performances
- "Just Works"
- Améliore les outils autour de l'écosystème et la DX 😍
- "Masque" la gestion des re-rendus et de la memoïsation 🫤
⚠️ Attention cependant !
⚠️ Attention cependant !
Le React Compiler n'est pas encore totalement prêt pour la production, il est toujours en phase de développement.
⚠️ Attention cependant !
Le React Compiler n'est pas encore totalement prêt pour la production, il est toujours en phase de développement.



Articles par Kevin Schiener
Références du talk :
- Code Source React Compiler 👩🏼💻
- Documentation React 📃
- Deep dive dans le React Compiler 📰 par YongSeok Jang
- Forget About Memo 📺 par Lauren Tan
- How the React compiler won't save you 📰 par Kevin Schiener
- React Compiler Deep Dive 📺 par Mofei Zhang et Sathya Gunasekaran
- Annonce React Forget 📺 par Xuan Huang
- React Compiler : In-Depth Beyond React Conf 2024 📺 Jack Herrington
- I tried React Compiler 📰 par Nadia Makarevich
- React Compiler Working Group 😍
React Compiler Working Group 😍

React Compiler Working Group 😍


Lauran Tan - React Team 🙏🏼
@potetotesUn avis ou une question ?
Lucas Audart

Feedback


Mickaël Alves

