React 20 Est Arrive: Server Actions Stable et Partial Prerendering Changent Tout
Salut HaWkers, React 20 est enfin la et ce n'est pas simplement une mise a jour incrementale. Cette version represente le plus grand changement architectural depuis les Hooks. Les Server Actions sont maintenant stables, le Partial Prerendering elimine l'ecran blanc, et le React Compiler fait de la memoisation automatique.
Si vous pensiez deja tout savoir sur React, preparez-vous a reapprendre certaines choses. Explorons tout ce qui a change.
Server Actions: La Star de React 20
Apres des mois en Canary, les Server Actions ont enfin gradue vers la version stable.
Que Sont les Server Actions
Les Server Actions permettent d'executer du code sur le serveur directement depuis des composants React, sans creer de routes API separees.
// Avant: Il fallait une route API + fetch cote client
// pages/api/submit.js
export default async function handler(req, res) {
const data = JSON.parse(req.body);
await saveToDatabase(data);
res.json({ success: true });
}
// component.jsx
async function handleSubmit(formData) {
const res = await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify(formData)
});
return res.json();
}// Apres: Server Action directement dans le composant
// actions.js
'use server'
export async function submitForm(formData) {
const name = formData.get('name');
const email = formData.get('email');
await saveToDatabase({ name, email });
return { success: true };
}
// component.jsx
import { submitForm } from './actions';
function ContactForm() {
return (
<form action={submitForm}>
<input name="name" required />
<input name="email" type="email" required />
<button type="submit">Envoyer</button>
</form>
);
}
Avantages Pratiques
1. Moins de Boilerplate:
// Routes API eliminees
// Pas de fetch() manuel
// Pas de gestion manuelle des etats de chargement
// TypeScript de bout en bout2. Progressive Enhancement:
// Le formulaire fonctionne meme sans JavaScript!
<form action={serverAction}>
{/* Si JS echoue, le form soumet quand meme */}
</form>3. Integration Avec useActionState:
'use client'
import { useActionState } from 'react';
import { submitForm } from './actions';
function Form() {
const [state, formAction, isPending] = useActionState(
submitForm,
{ message: '' }
);
return (
<form action={formAction}>
<input name="email" disabled={isPending} />
<button disabled={isPending}>
{isPending ? 'Envoi en cours...' : 'Envoyer'}
</button>
{state.message && <p>{state.message}</p>}
</form>
);
}
Partial Prerendering: Fin de l'Ecran Blanc
Le PPR (Partial Prerendering) resout l'un des problemes les plus anciens de React : le temps de chargement initial.
L'Ancien Probleme
L'utilisateur clique sur le lien
↓
Ecran blanc (chargement du JS)
↓
Ecran blanc (hydratation)
↓
Le contenu apparait (enfin!)
Temps total: 2-5 secondes sur les connexions lentesComment Fonctionne le PPR
L'utilisateur clique sur le lien
↓
Le contenu statique apparait IMMEDIATEMENT
↓
Les parties dynamiques arrivent en streaming
↓
Page entierement interactive
Temps pour le premier contenu: < 100msImplementation Pratique
// page.jsx - Partial Prerendering en action
import { Suspense } from 'react';
export default function ProductPage({ params }) {
return (
<main>
{/* Partie statique - rendue au build */}
<Header />
<ProductDetails id={params.id} />
{/* Partie dynamique - streaming */}
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews productId={params.id} />
</Suspense>
<Suspense fallback={<RecommendationsSkeleton />}>
<Recommendations userId={getCurrentUser()} />
</Suspense>
{/* Statique a nouveau */}
<Footer />
</main>
);
}
Metriques de Performance
Avant le PPR:
TTFB: 800ms
FCP: 2.1s
LCP: 3.2s
TTI: 4.5sApres le PPR:
TTFB: 50ms
FCP: 150ms
LCP: 800ms
TTI: 1.2sLes entreprises qui ont adopte le PPR rapportent des ameliorations massives des Core Web Vitals.
React Compiler: Memoisation Automatique
Vous vous souvenez de toute cette complexite avec useMemo, useCallback et React.memo? Le React Compiler s'en occupe automatiquement.
Avant: Memoisation Manuelle
// L'enfer de la memoisation manuelle
const MemoizedList = React.memo(function List({ items, onItemClick }) {
const sortedItems = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
const handleClick = useCallback(
(id) => {
onItemClick(id);
},
[onItemClick]
);
return (
<ul>
{sortedItems.map(item => (
<ListItem
key={item.id}
item={item}
onClick={handleClick}
/>
))}
</ul>
);
});
const ListItem = React.memo(function ListItem({ item, onClick }) {
return (
<li onClick={() => onClick(item.id)}>
{item.name}
</li>
);
});
Apres: Code Propre
// Le React Compiler gere l'optimisation
function List({ items, onItemClick }) {
const sortedItems = items.sort((a, b) =>
a.name.localeCompare(b.name)
);
return (
<ul>
{sortedItems.map(item => (
<ListItem
key={item.id}
item={item}
onClick={() => onItemClick(item.id)}
/>
))}
</ul>
);
}
function ListItem({ item, onClick }) {
return (
<li onClick={onClick}>
{item.name}
</li>
);
}
// Meme performance, code 60% plus courtActiver le Compiler
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
// Options
}]
]
};
// Ou dans Next.js 15+
// next.config.js
module.exports = {
experimental: {
reactCompiler: true
}
};
Asset Loading API
Nouvelle API pour un controle precis du chargement des ressources.
Priorisation Intelligente
import { preload, prefetch, preinit } from 'react-dom';
function App() {
// Preload critique - charge immediatement
preload('/critical-image.jpg', { as: 'image' });
// Prefetch - charge quand inactif
prefetch('/next-page-data.json', { as: 'fetch' });
// Preinit - initialise le script
preinit('/analytics.js', { as: 'script' });
return <MainContent />;
}Chargement Conditionnel
function ProductGallery({ products }) {
return (
<div>
{products.map((product, index) => {
// 4 premieres images: priorite haute
if (index < 4) {
preload(product.image, {
as: 'image',
fetchPriority: 'high'
});
}
return <ProductCard key={product.id} product={product} />;
})}
</div>
);
}
Hooks Ameliores
React 20 apporte des ameliorations significatives aux hooks existants.
useDeferredValue Etendu
function SearchResults({ query }) {
// Differencier les mises a jour non-urgentes
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
return (
<div style={{ opacity: isStale ? 0.7 : 1 }}>
<Results query={deferredQuery} />
</div>
);
}useOptimistic Pour une UI Optimiste
function TodoList({ todos, addTodo }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, { ...newTodo, pending: true }]
);
async function handleAdd(formData) {
const newTodo = { text: formData.get('text') };
// L'UI se met a jour immediatement
addOptimisticTodo(newTodo);
// Le serveur traite en arriere-plan
await addTodo(newTodo);
}
return (
<form action={handleAdd}>
<input name="text" />
<ul>
{optimisticTodos.map(todo => (
<li
key={todo.id}
style={{ opacity: todo.pending ? 0.5 : 1 }}
>
{todo.text}
</li>
))}
</ul>
</form>
);
}
Migration de React 19 Vers 20
La migration est relativement fluide, mais il y a des points d'attention.
Breaking Changes
// 1. forwardRef n'est plus necessaire
// Avant
const Input = forwardRef((props, ref) => (
<input ref={ref} {...props} />
));
// Apres
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
// 2. Context comme provider direct
// Avant
<ThemeContext.Provider value={theme}>
// Apres
<ThemeContext value={theme}>Checklist de Migration
# 1. Mettez a jour les dependances
npm install react@20 react-dom@20
# 2. Mettez a jour les types TypeScript
npm install @types/react@20
# 3. Executez les codemods
npx @react-codemod/update-react-imports
# 4. Verifiez les depreciations
npx react-upgrade-check
React Server Components Matures
Les RSC sont passes d'experimental a standard de production.
Architecture Recommandee
app/
├── layout.jsx # Server Component
├── page.jsx # Server Component
├── components/
│ ├── Header.jsx # Server Component
│ ├── Footer.jsx # Server Component
│ └── client/
│ ├── Form.jsx # 'use client'
│ └── Modal.jsx # 'use client'
└── actions/
└── submit.js # 'use server'Regle d'Or
// Par defaut: Server Components
// - Pas besoin de directive
// - Peuvent acceder a la base de donnees directement
// - N'ajoutent pas de JS au bundle client
// Client Components: uniquement quand necessaire
// - Interactivite (onClick, onChange)
// - Hooks navigateur (useState, useEffect)
// - APIs du navigateur (localStorage, etc)
'use client' // Uniquement quand c'est vraiment necessaire
Performance: Chiffres Reels
Comparatifs de projets migres vers React 20.
Bundle Size
React 19: 142 KB (gzipped)
React 20: 128 KB (gzipped)
Reduction: 10%Core Web Vitals (Moyenne)
Metrique | React 19 | React 20 | Amelioration
-----------|----------|----------|-------------
LCP | 2.1s | 0.9s | -57%
FID | 95ms | 42ms | -56%
CLS | 0.12 | 0.05 | -58%
INP | 180ms | 75ms | -58%Utilisation Memoire
Application moyenne:
React 19: 45MB heap
React 20: 32MB heap
Reduction: 29%Ce Qui Arrive Ensuite
React 20 n'est que le debut. La feuille de route indique :
React 21 (Preview)
- Activity API (remplace StrictMode)
- Support natif des animations
- Ameliorations de Suspense
- Rendu hors ecranEcosysteme
- Next.js 16 avec PPR par defaut
- Remix adoption complete des RSC
- React Native avec nouvelle architecture
Conclusion
React 20 n'est pas seulement une mise a jour, c'est une reimagination de la facon dont nous construisons des applications web. Les Server Actions eliminent le boilerplate, le PPR met fin aux ecrans blancs, et le Compiler supprime la complexite de l'optimisation manuelle.
Pour les developpeurs, cela signifie un code plus simple et de meilleures performances. Pour les utilisateurs, cela signifie des applications plus rapides et reactives.
Si vous n'avez pas encore commence a migrer, c'est le moment. Le futur de React est server-first, streaming-enabled et automatiquement optimise.
Si vous souhaitez continuer a suivre les nouveautes de l'ecosysteme, je recommande de jeter un oeil a un autre article : TypeScript 7 Natif en Go: 10x Plus Rapide ou nous explorons un autre grand changement qui transforme le developpement frontend.

