React natif Effect

Vos composants React, écrits comme des programmes Effect.

Le même composant tourne en SPA, sur un serveur, dans un Web Worker ou comme RSC — serveur ou client n’est qu’un détail de runtime.

MIT · React 19.2+ · Effect v4

La thèse

Deux fibres, un composant

React et Effect ordonnancent tous deux sur des fibres. effract pilote le générateur d’un composant dans la passe de rendu de React — un seul flux de yield* pour les deux. Du React 100 % réel, sans réconciliateur remplacé.

  • yield* Stats un service, résolu de façon synchrone
  • yield* hook(useState(0)) un vrai hook React, ordre stable
  • yield* fetchUser suspend, puis reprend sur place
  • une erreur remonte à l’error boundary la plus proche
counter.tsx
// Counter: a React component,
// written as an Effect program
const Counter = rec(function* () {
  const stats = yield* Stats
  const [n] = yield* hook(useState(0))
  return <Row n={n} of={stats.total}/>
})

// DI checked at compile time:
createRoot(el).render(
  mount(AppLive, Counter),
)

Un service et un vrai hook React dans un seul corps — vérifié à la compilation.

Un composant, tous les runtimes

Serveur ou client : un simple mount(...)

Layer navigateur → SPA. Layer serveur → SSR en flux. Moteur Flight → RSC. Le composant ne change jamais ; seul le runtime sous lui change.

SPA

Vite, dans le navigateur

SSR

Bun / Node en flux

Web Worker

hors du thread principal

RSC

Flight, en flux

Les mêmes RECs dans les quatre — démontré par les apps d’exemple.

Philosophie

Gardez la couche de rendu ennuyeuse

Un composant React doit être presque banal — structure et interaction, rien de plus. Le difficile vit hors de React, résolu au point de composition et remis à votre JSX en résultat typé.

Le difficile vit dans Effect

Retries, concurrence, cache, tracing — le travail d’Effect, hors de l’arbre de rendu, testable et réutilisable.

La composition async devient triviale

Plus d’états de chargement ni de hooks en cascade. Tout est résolu avant le rendu ; le corps se lit de haut en bas.

La bonne idée des RSC, sans le serveur

Le vrai intérêt des RSC : résoudre les dépendances à la racine de composition. effract le garde, sans le verrou.

Une primitive, pas un zoo

Remisez useEffect, une lib de fetch, le context, un store, les server actions — un seul yield* couvre les trois.

Pourquoi effract

Le call site, avant tout

01

Incrémental, pas une réécriture

Les composants ordinaires restent du <Component /> JSX. Un REC seulement là où il faut un service.

02

Du vrai React, de bout en bout

Hooks, Suspense, error boundaries, hydratation, RSC — tout fonctionne. effract rend à travers React.

03

Les services, en synchrone

Lire un service est une lecture de Context, pas un aller-retour async. Aucun Effect.runSync au call site.

04

Des signaux sans cérémonie

observe($ => $(count) * 2) re-rend exactement quand un atom lu change. Sans provider, sans sélecteurs.

05

RSC, nativement

Le même corps devient un Server Component async et émet du Flight standard.

06

Typé de bout en bout

Besoins et erreurs sont inférés depuis vos yield — mount ne compile pas sans eux.

Écrivez-le une fois. Exécutez-le partout où tourne un runtime.

MIT, sur npm. Commencez par la doc, ou les huit recettes de call site.