React 99 termes

99 termes affichés

TypeBestPractice Concept Method Pattern Principle Tool
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

'use client'

React 🟡 Mid

Directive qui marque un composant comme Client Component, activant l'interactivite (state, effets, handlers). Frontiere entre serveur et client dans l'arbre.

Comme le panneau 'zone libre-service' dans un magasin : a partir de la, c'est le client qui interagit.

'use client';

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Cas d'usage : Composants interactifs : formulaires, boutons, modales, tout ce qui a besoin de state ou d'event handlers.

Anti-pattern : Mettre 'use client' a la racine de l'app, perdant tous les avantages des Server Components.
#rendering#react19#nextjs

'use server'

React 🟡 Mid

Directive qui marque une fonction comme Server Action : elle s'execute sur le serveur mais peut etre appelee depuis le client, comme un RPC transparent.

Comme un bouton dans un ascenseur : tu appuies cote client, mais le moteur (serveur) fait tout le travail.

'use server';

export async function createUser(formData) {
  const name = formData.get('name');
  await db.insert({ name });
  revalidatePath('/users');
}

Cas d'usage : Mutations de donnees (formulaires, CRUD) sans creer de route API separee.

Anti-pattern : Mettre de la logique sensible cote client en oubliant que 'use server' cree un endpoint public.
#rendering#react19#nextjs

Action (React Router)

React 🟡 Mid

Fonction associee a une route qui gere les mutations de donnees (POST, PUT, DELETE) via les soumissions de formulaires natifs.

Comme la boite aux lettres d'un bureau : tu deposes ton courrier (formulaire), le bureau (action) le traite.

export async function createAction({ request }) {
  const formData = await request.formData();
  await api.createUser(Object.fromEntries(formData));
  return redirect('/users');
}
// Route: { path: 'users/new', action: createAction }

Cas d'usage : Gerer les soumissions de formulaires avec revalidation automatique des loaders apres mutation.

#routing#forms

Automatic Batching

React 🟡 Mid

React 18 regroupe automatiquement plusieurs mises a jour d'etat en un seul re-rendu, meme dans les callbacks asynchrones et les timeouts.

Comme un facteur qui attend d'avoir tout le courrier du quartier avant de faire sa tournee, au lieu d'un aller-retour par lettre.

// React 18: un seul re-rendu pour les deux
async function handleClick() {
  const data = await fetchData();
  setName(data.name);  // batch
  setAge(data.age);    // batch -> 1 seul rendu
}

Cas d'usage : Amelioration automatique des performances sans intervention du developpeur en React 18+.

Anti-pattern : Utiliser flushSync pour forcer des rendus synchrones sans raison valable.
#core#performance#react18

Bundle Analysis

React 🟡 Mid

Analyse visuelle du contenu du bundle JavaScript pour identifier les dependances lourdes et les opportunites de code splitting.

Comme une radio de valise a l'aeroport : tu vois exactement ce qui prend le plus de place dans ton bagage.

// Avec @next/bundle-analyzer
// next.config.js
const withAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});
module.exports = withAnalyzer(nextConfig);
// ANALYZE=true npm run build

Cas d'usage : Diagnostiquer pourquoi le bundle est trop gros et prioriser les optimisations de taille.

#performance#devtools

Code Splitting

React 🟡 Mid

Technique qui decoupe le bundle JS en morceaux charges a la demande via React.lazy et import() dynamique, reduisant le temps de chargement initial.

Comme un buffet a volonte : tu ne prends que ce que tu vas manger maintenant, pas tout le menu d'un coup.

const AdminPanel = React.lazy(() => import('./AdminPanel'));

function App() {
  return (
    <Suspense fallback={<Spinner />}>
      {isAdmin && <AdminPanel />}
    </Suspense>
  );
}

Cas d'usage : Pages lourdes (admin, dashboard), composants conditionels, routes non critiques.

Anti-pattern : Splitter des composants minuscules, augmentant le nombre de requetes HTTP sans gain significatif.
#performance#interview

Component Lifecycle

React 🟢 Junior

Les differentes phases d'un composant : montage, mise a jour et demontage. En hooks, useEffect gere ces phases.

Comme la vie d'un employe : embauche (mount), promotions (update), depart (unmount).

useEffect(() => {
  console.log('Monte ou mis a jour');
  return () => console.log('Demonte / cleanup');
}, [dep]); // se relance si dep change

Cas d'usage : Gerer les effets de bord comme les abonnements, les appels API ou les timers.

Anti-pattern : Oublier la fonction de cleanup, causant des fuites memoire avec des abonnements non annules.
#core#interview#hooks

Compound Components

React 🟡 Mid

Pattern ou un composant parent partage son etat implicitement avec ses enfants via Context, offrant une API declarative et flexible.

Comme un menu deroulant HTML <select>/<option> : les options savent qu'elles font partie du select sans configuration explicite.

// Utilisation declarative
<Tabs>
  <Tabs.List>
    <Tabs.Tab>Profil</Tabs.Tab>
    <Tabs.Tab>Settings</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panels>
    <Tabs.Panel>Contenu profil</Tabs.Panel>
    <Tabs.Panel>Contenu settings</Tabs.Panel>
  </Tabs.Panels>
</Tabs>

Cas d'usage : Composants UI complexes (tabs, accordeons, menus) necessitant une API flexible et composable.

Anti-pattern : Utiliser ce pattern pour des composants simples ou une prop suffirait.
#patterns#interview#design

Concurrent Rendering

React 🔴 Senior

Mode de rendu ou React peut interrompre, reprendre et abandonner des rendus en cours pour prioriser les interactions utilisateur urgentes.

Comme un serveur de restaurant qui interrompt la preparation d'une commande pour repondre a un client qui attend a la caisse.

// Active automatiquement avec createRoot
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);

Cas d'usage : Garder l'interface reactive pendant des rendus lourds (longues listes, calculs complexes).

Anti-pattern : Utiliser ReactDOM.render() legacy qui ne beneficie pas du rendu concurrent.
#core#interview#performance

Container/Presentational

React 🟢 Junior

Pattern qui separe les composants en deux types : Container (logique, data fetching) et Presentational (UI pure, recoit des props). Moins pertinent avec les hooks.

Comme un realisateur (container) et un acteur (presentational) : l'un dirige, l'autre joue le role.

// Presentational : UI pure
function UserCard({ name, avatar }) {
  return <div><img src={avatar} /><p>{name}</p></div>;
}
// Container : logique
function UserCardContainer({ userId }) {
  const { data } = useQuery({ queryKey: ['user', userId], queryFn: fetchUser });
  return <UserCard name={data?.name} avatar={data?.avatar} />;
}

Cas d'usage : Rendre les composants UI reutilisables et testables en les separant de la logique.

#patterns#interview

Context API

React 🟡 Mid

Systeme de partage de donnees sans prop drilling via createContext, Provider et useContext. Attention : chaque changement de valeur re-rend TOUS les consommateurs.

Comme un haut-parleur dans un magasin : tout le monde entend l'annonce, meme ceux qui ne sont pas concernes.

const AuthCtx = createContext(null);

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  return (
    <AuthCtx.Provider value={{ user, setUser }}>
      {children}
    </AuthCtx.Provider>
  );
}

Cas d'usage : Donnees peu changeantes (theme, auth, locale) partagees a travers l'arbre.

Anti-pattern : Stocker du state frequemment mis a jour dans Context sans le decouper, causant des re-rendus en cascade.
#state#interview#core

Controlled vs Uncontrolled

React 🟢 Junior

Controlled : la valeur est geree par React (via state + onChange). Uncontrolled : la valeur est geree par le DOM (via ref et defaultValue).

Controlled = GPS qui te guide a chaque virage. Uncontrolled = carte papier que tu consultes quand tu veux.

// Controlled
const [val, setVal] = useState('');
<input value={val} onChange={e => setVal(e.target.value)} />

// Uncontrolled
const ref = useRef();
<input defaultValue="" ref={ref} />
// ref.current.value pour lire

Cas d'usage : Controlled pour validation en temps reel, uncontrolled pour formulaires simples ou performance critique.

Anti-pattern : Passer de controlled a uncontrolled (ou inversement) pendant la vie du composant.
#forms#interview#fundamentals

createAsyncThunk

React 🟡 Mid

Fonction RTK qui genere automatiquement un thunk avec les actions pending/fulfilled/rejected pour les operations asynchrones.

Comme un livreur avec suivi : tu sais quand il part (pending), arrive (fulfilled) ou echoue (rejected).

const fetchUsers = createAsyncThunk(
  'users/fetch',
  async (_, { rejectWithValue }) => {
    try { return (await api.getUsers()).data; }
    catch (e) { return rejectWithValue(e.message); }
  }
);

Cas d'usage : Appels API avec gestion automatique des etats de chargement et d'erreur dans Redux.

Anti-pattern : Ignorer le rejectWithValue et laisser les erreurs non gerees dans les extra reducers.
#state#async

createSelector (RTK)

React 🟡 Mid

Fonction de Reselect (integree a RTK) qui cree des selecteurs memoises. Le resultat n'est recalcule que si les inputs changent, evitant des calculs redondants.

Comme un formulaire pre-rempli : tant que les donnees source ne changent pas, le calcul derive est reutilise.

const selectUsers = (state) => state.users.list;
const selectActiveUsers = createSelector(
  [selectUsers],
  (users) => users.filter(u => u.active)
);
// Ne refiltre que si state.users.list change

Cas d'usage : Derivation de donnees couteuses depuis le store Redux (filtrage, tri, aggregation).

Anti-pattern : Creer un nouveau selecteur a chaque rendu en l'instanciant dans le composant.
#state#performance

CSR (Client-Side Rendering)

React 🟢 Junior

Le serveur envoie un HTML vide avec un bundle JS. Le navigateur execute React pour generer le DOM. Mauvais pour le SEO et le premier affichage.

Comme recevoir des meubles en kit : le client (navigateur) doit tout assembler lui-meme avant de pouvoir s'asseoir.

// index.html minimal
// <div id="root"></div>
// <script src="bundle.js"></script>

import { createRoot } from 'react-dom/client';
createRoot(document.getElementById('root')).render(<App />);

Cas d'usage : Dashboards internes, apps behind auth ou le SEO n'est pas critique.

Anti-pattern : Utiliser CSR pour un site public qui a besoin de SEO (blog, e-commerce).
#rendering#interview#architecture

Custom Hook

React 🟡 Mid

Fonction JavaScript prefixee par 'use' qui encapsule de la logique reutilisable composee d'autres hooks. Chaque appel cree sa propre instance de state.

Comme une recette de cuisine : tu la reutilises dans differents repas, mais chaque plat a ses propres ingredients (state).

function useDebounce(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}

Cas d'usage : Extraire et reutiliser de la logique stateful entre composants (fetch, debounce, form, auth).

Anti-pattern : Creer un custom hook pour encapsuler du code qui ne contient aucun hook : une simple fonction suffit.
#hooks#interview#patterns

Cypress Component Testing

React 🟡 Mid

Mode de test Cypress qui monte des composants React dans un vrai navigateur, permettant des tests visuels et d'interaction sans lancer toute l'application.

Comme tester une piece de voiture sur un banc d'essai reel au lieu d'une simulation informatique.

import { mount } from 'cypress/react';

it('affiche le compteur', () => {
  mount(<Counter initial={5} />);
  cy.get('[data-testid="count"]').should('have.text', '5');
  cy.get('button').click();
  cy.get('[data-testid="count"]').should('have.text', '6');
});

Cas d'usage : Tests d'interaction complexes (drag & drop, animations) necessitant un vrai navigateur.

#testing#e2e

EntityAdapter (RTK)

React 🟡 Mid

Utilitaire RTK qui genere un ensemble de reducers et selecteurs pour gerer des collections normalisees (ids + entities) avec operations CRUD pre-construites.

Comme un classeur a fiches avec index : ajout, suppression et recherche sont automatises et optimises.

const usersAdapter = createEntityAdapter();
const usersSlice = createSlice({
  name: 'users',
  initialState: usersAdapter.getInitialState(),
  reducers: {
    addUser: usersAdapter.addOne,
    removeUser: usersAdapter.removeOne,
  }
});

Cas d'usage : Collections d'entites (utilisateurs, produits, commentaires) necessitant des operations CRUD normalisees.

#state#patterns

Error Boundary

React 🟡 Mid

Composant classe qui intercepte les erreurs JavaScript dans son sous-arbre et affiche un UI de secours au lieu de crasher toute l'application.

Comme un fusible electrique : il saute pour proteger le reste du circuit.

class ErrorBoundary extends React.Component {
  state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  render() {
    if (this.state.hasError) return <p>Oups!</p>;
    return this.props.children;
  }
}

Cas d'usage : Encapsuler des sections critiques pour que le reste de l'app continue de fonctionner en cas d'erreur.

Anti-pattern : Ne pas logger l'erreur dans componentDidCatch, perdant des informations precieuses en production.
#core#interview#resilience

Fragment

React 🟢 Junior

Conteneur invisible qui permet de retourner plusieurs elements sans ajouter de noeud DOM supplementaire.

Comme un trombone pour regrouper des feuilles : il les tient ensemble sans ajouter de page vide.

function Info() {
  return (
    <>
      <h1>Titre</h1>
      <p>Description</p>
    </>
  );
}

Cas d'usage : Eviter les divs inutiles qui cassent le layout CSS ou la semantique HTML.

#core#syntax

Headless Components

React 🔴 Senior

Composants qui fournissent la logique et l'accessibilite sans imposer de style ni de markup. L'utilisateur controle entierement le rendu.

Comme un moteur de voiture vendu sans carrosserie : tu choisis la forme, il fournit la puissance.

// Headless UI Combobox
<Combobox value={selected} onChange={setSelected}>
  <Combobox.Input onChange={e => setQuery(e.target.value)} />
  <Combobox.Options>
    {filtered.map(item => (
      <Combobox.Option key={item.id} value={item}>{item.name}</Combobox.Option>
    ))}
  </Combobox.Options>
</Combobox>

Cas d'usage : Design systems, librairies UI (Headless UI, Radix, Downshift) qui doivent etre stylisables sans contrainte.

#patterns#design-system#a11y

Fonction qui prend un composant et retourne un nouveau composant enrichi. Pattern classique de reutilisation de logique, largement remplace par les hooks.

Comme un cadre photo qui embellit toute photo qu'on y met : le HOC ajoute des fonctionnalites a tout composant.

function withAuth(Component) {
  return function AuthWrapper(props) {
    const { user } = useAuth();
    if (!user) return <Redirect to="/login" />;
    return <Component {...props} user={user} />;
  };
}
const ProtectedPage = withAuth(Dashboard);

Cas d'usage : Ajouter de la logique transverse (auth, logging, theming) a plusieurs composants.

Anti-pattern : Empiler trop de HOCs, creant un 'wrapper hell' et rendant le debugging difficile.
#patterns#interview

Infinite Query

React 🟡 Mid

Pattern TanStack Query pour le scroll infini ou le 'charger plus'. useInfiniteQuery gere automatiquement les pages, le curseur et la concatenation des resultats.

Comme un rouleau de papier toilette : tu en deroules plus quand tu en as besoin, page apres page.

const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
  queryKey: ['posts'],
  queryFn: ({ pageParam = 0 }) => fetchPosts(pageParam),
  getNextPageParam: (lastPage) => lastPage.nextCursor,
});
// data.pages contient toutes les pages chargees

Cas d'usage : Feeds sociaux, listes de produits, tout contenu pagine avec scroll infini ou bouton 'charger plus'.

#data-fetching#ux

Intercepting Routes

React 🔴 Senior

Permet d'intercepter une route pour afficher son contenu dans le layout actuel (ex: modale) au lieu de naviguer vers la page complete.

Comme un apercu rapide au survol : tu vois le contenu sans quitter ta page, mais l'URL directe montre la version complete.

// app/@modal/(.)photo/[id]/page.tsx
// Le (.) intercepte /photo/[id]
export default function PhotoModal({ params }) {
  return (
    <Modal>
      <Photo id={params.id} />
    </Modal>
  );
}
// URL directe /photo/123 -> page complete

Cas d'usage : Photos en modale (Instagram-like), apercu de produit, detail de notification sans quitter le feed.

#nextjs#routing#advanced

invalidateQueries

React 🟡 Mid

Methode TanStack Query qui marque des requetes en cache comme perimees, declenchant un refetch automatique si elles sont actuellement utilisees.

Comme tirer la chasse d'eau du cache : les donnees perimees sont evacuees et de nouvelles arrivent.

const queryClient = useQueryClient();

// Invalider toutes les requetes 'users'
queryClient.invalidateQueries({ queryKey: ['users'] });

// Invalider un user specifique
queryClient.invalidateQueries({ queryKey: ['users', userId] });

Cas d'usage : Apres une mutation reussie, forcer le rechargement des donnees affectees dans le cache.

Anti-pattern : Invalider trop large (toutes les queries) au lieu de cibler les queryKeys specifiques.
#data-fetching

Combine SSG et SSR : les pages sont generees statiquement mais regenerees en arriere-plan apres un delai configurable (revalidate). Introduit par Next.js.

Comme un menu du jour affiche a l'entree : il est pre-imprime mais le serveur le remplace discretement chaque jour.

// Next.js App Router
export const revalidate = 3600; // regenere toutes les heures

export default async function Products() {
  const products = await getProducts();
  return <ProductGrid products={products} />;
}

Cas d'usage : Pages e-commerce, catalogues : contenu relativement stable mais qui doit se mettre a jour sans rebuild complet.

#rendering#performance#nextjs

Jotai

React 🟡 Mid

Gestion d'etat atomique pour React. Chaque atome est une unite de state independante, composable et reactive, sans Provider obligatoire.

Comme des briques LEGO : chaque brique (atome) est independante et tu les assembles pour construire ton state.

const countAtom = atom(0);
const doubleAtom = atom((get) => get(countAtom) * 2);

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Cas d'usage : State atomique granulaire quand chaque composant n'a besoin que d'une fraction de l'etat global.

#state#ecosystem

JSX

React 🟢 Junior

Syntaxe qui permet d'ecrire du HTML dans du JavaScript. Le compilateur le transforme en appels React.createElement().

C'est comme un moule a gateau : tu dessines la forme en HTML, et React coule le JavaScript dedans.

// JSX compile en createElement
const el = <h1 className="title">Bonjour</h1>;
// equivalent a :
const el2 = React.createElement('h1', { className: 'title' }, 'Bonjour');

Cas d'usage : Utilise dans chaque composant React pour decrire l'interface de maniere declarative.

Anti-pattern : Oublier que class s'ecrit className et for s'ecrit htmlFor en JSX.
#core#interview#syntax

Key Prop

React 🟢 Junior

Attribut special qui aide React a identifier chaque element dans une liste. Permet une reconciliation efficace sans reconstruire tout le DOM.

Comme les numeros de dossards dans une course : React sait qui est qui meme si l'ordre change.

// Correct: identifiant unique
items.map(item => <li key={item.id}>{item.name}</li>)

// Anti-pattern: index comme key
items.map((item, i) => <li key={i}>{item.name}</li>)

Cas d'usage : Obligatoire dans toute liste dynamique pour eviter des bugs de rendu et ameliorer les performances.

Anti-pattern : Utiliser l'index comme key dans une liste qui peut etre triee, filtree ou modifiee, causant des bugs d'etat.
#core#interview#performance

Loader (React Router)

React 🟡 Mid

Fonction associee a une route qui charge les donnees avant le rendu du composant. Les donnees sont accessibles via useLoaderData().

Comme un serveur qui prepare ta table avant que tu arrives : tout est pret quand tu t'assois.

// Definition
export async function userLoader({ params }) {
  return fetch(`/api/users/${params.id}`);
}
// Route: { path: 'users/:id', loader: userLoader, element: <User /> }
// Composant
function User() {
  const user = useLoaderData();
  return <p>{user.name}</p>;
}

Cas d'usage : Pre-charger les donnees d'une page avant le rendu pour eviter les waterfalls de fetching.

#routing#data-fetching

MSW (Mock Service Worker)

React 🟡 Mid

Outil qui intercepte les requetes reseau au niveau du Service Worker pour les mocker, sans modifier le code applicatif. Fonctionne en test et en dev.

Comme un doubleur de voix au cinema : le vrai acteur (API) est absent mais la scene (test) se joue quand meme.

import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(
  http.get('/api/users', () => HttpResponse.json([
    { id: 1, name: 'Alice' }
  ]))
);
beforeAll(() => server.listen());

Cas d'usage : Mocker les API dans les tests et pendant le developpement frontend sans backend disponible.

#testing#mocking

Mutation (TanStack Query)

React 🟡 Mid

Operation d'ecriture (POST, PUT, DELETE) geree par useMutation avec callbacks onSuccess/onError et possibilite de mises a jour optimistes.

Comme un formulaire de La Poste : tu le remplis (mutate), tu sais si c'est envoye (onSuccess) ou perdu (onError).

const mutation = useMutation({
  mutationFn: (newUser) => api.post('/users', newUser),
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['users'] });
  },
});
mutation.mutate({ name: 'Alice' });

Cas d'usage : Toute operation d'ecriture vers le serveur avec invalidation automatique du cache apres succes.

#data-fetching

Nested Routes

React 🟡 Mid

Routes imbriquees ou les routes enfants s'affichent a l'interieur du layout de leur route parent via Outlet, permettant des layouts partages et une navigation hierarchique.

Comme des poupees russes : chaque layout contient le suivant, et seul le contenu le plus interne change.

// /dashboard -> Layout + DashboardHome
// /dashboard/settings -> Layout + Settings
<Route path="dashboard" element={<DashLayout />}>
  <Route index element={<DashHome />} />
  <Route path="settings" element={<Settings />} />
</Route>

Cas d'usage : Applications avec des layouts hierarchiques (sidebar fixe, breadcrumbs dynamiques, multi-step wizards).

#routing

Next.js App Router

React 🟡 Mid

Systeme de routage Next.js base sur le filesystem avec Server Components par defaut, layouts imbriques, et conventions de fichiers (page, layout, loading, error).

Comme un immeuble ou chaque dossier est un etage et chaque fichier est une piece avec un role precis.

// app/users/[id]/page.tsx
export default async function UserPage({ params }) {
  const { id } = await params;
  const user = await getUser(id);
  return <h1>{user.name}</h1>;
}
// app/users/[id]/loading.tsx -> Suspense automatique
// app/users/[id]/error.tsx -> Error Boundary auto

Cas d'usage : Applications React full-stack avec SSR, RSC, routing et API integres.

#nextjs#interview#framework

Next.js Middleware

React 🟡 Mid

Code qui s'execute avant chaque requete dans Next.js, au niveau Edge. Permet la redirection, la reecriture d'URL, l'ajout de headers et l'auth.

Comme un vigile a l'entree d'un batiment : il verifie ton badge avant de te laisser entrer dans n'importe quelle piece.

// middleware.ts (racine du projet)
import { NextResponse } from 'next/server';

export function middleware(request) {
  const token = request.cookies.get('token');
  if (!token) return NextResponse.redirect(new URL('/login', request.url));
  return NextResponse.next();
}
export const config = { matcher: ['/dashboard/:path*'] };

Cas d'usage : Auth, redirection A/B testing, geolocalisation, rate limiting au niveau Edge.

Anti-pattern : Mettre de la logique lourde (requetes DB) dans le middleware Edge qui a des limitations runtime.
#nextjs#auth#edge

Optimistic UI Forms

React 🟡 Mid

Pattern combinant useOptimistic et useFormStatus pour afficher immediatement le resultat d'une soumission de formulaire avant la confirmation serveur.

Comme un tchat ou ton message s'affiche instantanement avec une horloge, puis la coche de confirmation arrive du serveur.

function TodoForm({ addTodo }) {
  const [optimistic, setOptimistic] = useOptimistic(todos);
  async function action(formData) {
    setOptimistic(prev => [...prev, { text: formData.get('text'), pending: true }]);
    await addTodo(formData);
  }
  return <form action={action}><input name="text" /><SubmitBtn /></form>;
}

Cas d'usage : Formulaires ou la latence percue nuit a l'UX : chat, commentaires, listes de taches.

#forms#ux#react19

Optimistic Update

React 🟡 Mid

Technique qui met a jour l'UI immediatement avant la confirmation serveur, puis annule en cas d'echec. Ameliore la perception de vitesse.

Comme celebrer un but avant la validation VAR : si le but est annule, on revient a l'etat precedent.

useMutation({
  mutationFn: updateTodo,
  onMutate: async (newTodo) => {
    await queryClient.cancelQueries({ queryKey: ['todos'] });
    const prev = queryClient.getQueryData(['todos']);
    queryClient.setQueryData(['todos'], old => [...old, newTodo]);
    return { prev };
  },
  onError: (_, __, ctx) => queryClient.setQueryData(['todos'], ctx.prev),
});

Cas d'usage : Actions utilisateur frequentes (like, toggle, reorder) ou la latence reseau degrade l'UX.

#data-fetching#ux#patterns

Outlet

React 🟡 Mid

Composant React Router qui rend la route enfant correspondante dans un layout parent, permettant des layouts imbriques partageant du UI commun.

Comme un cadre photo dans un salon : le salon (layout) reste, mais la photo (enfant) change selon la page.

function Layout() {
  return (
    <div>
      <Navbar />
      <main><Outlet /></main> {/* route enfant ici */}
      <Footer />
    </div>
  );
}

Cas d'usage : Layouts partages (sidebar, header, footer) avec du contenu qui change selon la route active.

#routing

Parallel Routes

React 🔴 Senior

Fonctionnalite Next.js App Router qui permet de rendre plusieurs pages simultanement dans le meme layout via des slots nommes (@slot).

Comme un ecran divise en deux sur ta TV : tu regardes deux chaines en meme temps dans le meme cadre.

// app/layout.tsx
export default function Layout({ children, analytics, team }) {
  return (
    <div>
      {children}
      {analytics} {/* @analytics/page.tsx */}
      {team}       {/* @team/page.tsx */}
    </div>
  );
}

Cas d'usage : Dashboards avec plusieurs panneaux independants, modales comme routes, vues conditionnelles.

#nextjs#routing#advanced

Partial Prerendering

React 🔴 Senior

Fonctionnalite Next.js experimentale combinant une coquille statique (servie depuis le CDN) avec des trous dynamiques remplis en streaming. Le meilleur des deux mondes.

Comme un journal avec des encarts pub personnalises : le journal est imprime d'avance, mais les pubs changent par lecteur.

// La coquille statique est pre-rendue
// Les parties dynamiques sont wrappees dans Suspense
export default function Page() {
  return (
    <StaticHeader />
    <Suspense fallback={<CartSkeleton />}>
      <DynamicCart /> {/* stream dynamique */}
    </Suspense>
  );
}

Cas d'usage : Pages e-commerce avec header statique rapide et panier/prix dynamiques streames.

#rendering#nextjs#performance

placeholderData

React 🟡 Mid

Option TanStack Query qui fournit des donnees temporaires pendant le chargement initial, sans les stocker dans le cache. Evite le flash de loading.

Comme une maquette de vitrine : elle montre la disposition avant que les vrais produits arrivent.

useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
  placeholderData: (previousData) => previousData,
  // ou: placeholderData: { name: 'Chargement...', email: '' }
});

Cas d'usage : Afficher les donnees precedentes pendant une transition entre pages ou profils utilisateur.

#data-fetching#ux

Polymorphic Components

React 🔴 Senior

Composants qui peuvent changer leur element HTML racine via une prop 'as' ou 'component', tout en conservant un typage TypeScript correct.

Comme un costume transformable : le meme vetement peut devenir veste, gilet ou manteau selon le bouton presse.

function Box<C extends React.ElementType = 'div'>(
  { as, children, ...props }: { as?: C } & React.ComponentPropsWithoutRef<C>
) {
  const Component = as || 'div';
  return <Component {...props}>{children}</Component>;
}
<Box as="section">...</Box>
<Box as="a" href="/">Lien</Box>

Cas d'usage : Design systems ou un meme composant stylise doit s'adapter a differents elements HTML semantiques.

#patterns#typescript#design-system

Portal

React 🟡 Mid

Permet de rendre un composant enfant dans un noeud DOM situe en dehors de la hierarchie du parent. Les evenements remontent toujours dans l'arbre React.

Comme un tunnel secret : le composant vit dans la maison React mais sort par une porte cachee dans un autre endroit du DOM.

import { createPortal } from 'react-dom';

function Modal({ children }) {
  return createPortal(
    <div className="modal">{children}</div>,
    document.getElementById('modal-root')
  );
}

Cas d'usage : Modales, tooltips, menus deroulants qui doivent echapper au overflow:hidden du parent.

Anti-pattern : Utiliser un portal sans gerer le focus trapping pour l'accessibilite.
#core#advanced#a11y

prefetchQuery

React 🟡 Mid

Methode de TanStack Query pour pre-charger des donnees en cache avant qu'elles ne soient necessaires, eliminant le temps de chargement visible.

Comme prechauffer le four avant d'enfourner : quand tu en as besoin, tout est deja pret.

// Prefetch au hover d'un lien
<Link
  onMouseEnter={() => {
    queryClient.prefetchQuery({
      queryKey: ['user', userId],
      queryFn: () => fetchUser(userId),
    });
  }}
/>

Cas d'usage : Pre-charger les donnees de la prochaine page au survol d'un lien ou pendant un formulaire multi-etapes.

#data-fetching#performance

Profiler API

React 🟡 Mid

Composant React et onglet DevTools qui mesurent le cout de rendu d'un sous-arbre : frequence, duree et raison des re-rendus.

Comme un chronometre pour chaque coureur dans un relais : tu identifies qui ralentit l'equipe.

<Profiler id="Navigation" onRender={(id, phase, duration) => {
  console.log(`${id} ${phase}: ${duration.toFixed(1)}ms`);
}}>
  <Nav items={items} />
</Profiler>

Cas d'usage : Identifier les composants les plus lents pour cibler les optimisations de performance.

#performance#devtools

Progressive Enhancement

React 🟡 Mid

Principe ou l'application fonctionne sans JavaScript (formulaires HTML natifs, liens) puis s'ameliore progressivement avec JS pour une meilleure UX.

Comme un escalier avec un escalator a cote : ca marche a pied (sans JS), mais c'est mieux avec le moteur (JS).

// Le formulaire fonctionne meme sans JS
<form action={serverAction} method="POST">
  <input name="email" required />
  <SubmitButton /> {/* desactive pendant l'envoi si JS actif */}
</form>

Cas d'usage : Applications critiques (e-commerce, admin) qui doivent rester fonctionnelles meme si le JS echoue.

#rendering#a11y#bestpractice

Prop Getter Pattern

React 🔴 Senior

Pattern qui fournit des fonctions (getInputProps, getToggleProps) retournant les props necessaires pour un element, fusionnant les props utilisateur avec celles du composant.

Comme un styliste qui te donne un ensemble complet : tu peux ajouter tes accessoires, il gere l'harmonie du tout.

function useSelect() {
  const [isOpen, setOpen] = useState(false);
  const getToggleProps = (userProps = {}) => ({
    'aria-expanded': isOpen,
    onClick: () => { userProps.onClick?.(); setOpen(!isOpen); },
    ...userProps,
  });
  return { isOpen, getToggleProps };
}
<button {...getToggleProps({ className: 'btn' })}>Toggle</button>

Cas d'usage : Composants headless et librairies qui doivent gerer l'accessibilite tout en restant flexibles.

#patterns#advanced#a11y

Props

React 🟢 Junior

Donnees passees d'un composant parent a un composant enfant, en lecture seule. C'est le mecanisme principal de communication descendante.

Comme les ingredients donnes a un cuisinier : il les utilise mais ne les modifie pas pour le fournisseur.

function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}
<Card title="Bienvenue">Contenu ici</Card>

Cas d'usage : Rendre un composant reutilisable en parametrant son comportement et son contenu.

Anti-pattern : Passer trop de props (prop drilling) au lieu d'utiliser Context ou la composition.
#core#interview#fundamentals

Provider Pattern

React 🟡 Mid

Pattern qui utilise Context.Provider pour fournir des donnees ou des services a un sous-arbre de composants, sans prop drilling.

Comme le Wi-Fi d'un batiment : tous les appareils dans la zone y accedent sans cable direct.

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}
// Usage: <ThemeProvider><App /></ThemeProvider>

Cas d'usage : Fournir des services globaux (theme, i18n, auth, feature flags) a toute l'application.

Anti-pattern : Creer un 'Provider Hell' avec 15 providers imbriques a la racine sans les composer.
#patterns#interview

queryKey

React 🟡 Mid

Identifiant unique d'une requete dans TanStack Query, utilise pour le cache, la deduplication et l'invalidation. Generalement un tableau hierarchique.

Comme l'etiquette d'un tiroir de rangement : elle dit exactement ce qu'il y a dedans et permet de le retrouver.

// Hierarchique pour une invalidation fine
useQuery({ queryKey: ['users'] });
useQuery({ queryKey: ['users', userId] });
useQuery({ queryKey: ['users', userId, 'posts'] });

// Invalider tout ce qui commence par 'users'
queryClient.invalidateQueries({ queryKey: ['users'] });

Cas d'usage : Structurer les cles de facon hierarchique pour pouvoir invalider a differents niveaux de granularite.

Anti-pattern : Utiliser des strings simples au lieu de tableaux hierarchiques, rendant l'invalidation partielle impossible.
#data-fetching

React Fiber

React 🔴 Senior

Architecture interne de React (depuis v16) qui decoupe le rendu en unites de travail interruptibles. Permet le rendu concurrent et la priorisation des mises a jour.

Comme un chef cuisinier qui peut interrompre la preparation d'un plat pour servir un client urgent, puis reprendre ou il en etait.

// Fiber permet les priorites
// Haute priorite: saisie utilisateur
// Basse priorite: mise a jour d'une liste
const [query, setQuery] = useState('');
const [results, setResults] = useTransition();

Cas d'usage : Fondation du concurrent rendering, permet a React de rester reactif meme avec des rendus lourds.

#core#interview#architecture

React Hook Form

React 🟡 Mid

Librairie de formulaires performante basee sur les refs (uncontrolled). Minimise les re-rendus et offre une validation integree avec support de Zod, Yup, etc.

Comme un formulaire papier : tu remplis tout d'un coup et la validation se fait a la soumission, pas a chaque lettre.

const { register, handleSubmit, formState: { errors } } = useForm();

<form onSubmit={handleSubmit(onSubmit)}>
  <input {...register('email', { required: true })} />
  {errors.email && <span>Email requis</span>}
  <button type="submit">Envoyer</button>
</form>

Cas d'usage : Formulaires complexes avec beaucoup de champs ou la performance est critique.

Anti-pattern : Re-implementer la validation manuellement avec useState au lieu d'utiliser les resolvers integres.
#forms#interview#ecosystem

React Router v6

React 🟡 Mid

Librairie de routage standard pour React avec routes imbriquees, loaders de donnees, actions de mutation et navigation declarative.

Comme le plan d'un centre commercial avec les fleches directionnelles : chaque URL mene a la bonne boutique (composant).

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'users/:id', element: <User />, loader: userLoader },
    ]
  }
]);

Cas d'usage : SPA React sans framework (Vite + React) qui a besoin de navigation multi-pages.

Anti-pattern : Imbriquer des BrowserRouter au lieu d'utiliser des routes imbriquees avec Outlet.
#routing#interview#ecosystem

React Server Components

React 🔴 Senior

Composants qui s'executent uniquement sur le serveur, avec acces direct aux bases de donnees et fichiers. Leur code n'est pas envoye au client, reduisant le bundle JS.

Comme la cuisine d'un restaurant : le client ne voit que le plat (HTML), pas les ustensiles (code serveur).

// Server Component (par defaut dans Next.js App Router)
export default async function UserList() {
  const users = await db.query('SELECT * FROM users');
  return (
    <ul>
      {users.map(u => <li key={u.id}>{u.name}</li>)}
    </ul>
  );
}

Cas d'usage : Composants qui affichent des donnees sans interactivite : listes, articles, dashboards de lecture.

Anti-pattern : Essayer d'utiliser useState ou onClick dans un Server Component : il faut 'use client' pour ca.
#rendering#interview#react19#nextjs

React Testing Library

React 🟡 Mid

Librairie de test qui encourage les tests du point de vue de l'utilisateur. On interagit via roles, labels et texte visible, pas via les details d'implementation.

Comme un testeur mystere dans un restaurant : il teste l'experience client, pas la recette du chef.

import { render, screen, fireEvent } from '@testing-library/react';

test('incremente le compteur', () => {
  render(<Counter />);
  fireEvent.click(screen.getByRole('button', { name: /incrementer/i }));
  expect(screen.getByText('1')).toBeInTheDocument();
});

Cas d'usage : Tests unitaires et d'integration de composants React, focus sur le comportement utilisateur.

Anti-pattern : Tester les details d'implementation (state interne, nombre de re-rendus) au lieu du comportement.
#testing#interview#bestpractice

React.memo

React 🟡 Mid

HOC qui memoize un composant : il ne se re-rend que si ses props changent (comparaison shallow par defaut).

Comme un videur de boite de nuit qui ne laisse passer que les nouvelles tetes : memes props = on ne re-rend pas.

const ExpensiveList = React.memo(function List({ items }) {
  return items.map(i => <Item key={i.id} {...i} />);
});

// Avec comparateur custom
const MemoComp = React.memo(Comp, (prev, next) => {
  return prev.id === next.id;
});

Cas d'usage : Composants enfants couteux qui re-rendent inutilement a cause du re-rendu du parent.

Anti-pattern : Utiliser React.memo sur tous les composants sans mesurer : le cout de comparaison peut depasser le gain.
#performance#interview

Reconciliation Algorithm

React 🟡 Mid

Algorithme de diffing qui compare deux arbres Virtual DOM pour determiner les changements minimaux a appliquer au vrai DOM. Complexite O(n) grace a des heuristiques.

Comme un jeu des 7 differences : React compare les deux images et ne corrige que les pixels differents.

// React compare par type d'element et key
// Si le type change: detruit et recree le sous-arbre
// Si le type est identique: met a jour les props
<ul>
  <li key="a">A</li> {/* key aide la reconciliation */}
  <li key="b">B</li>
</ul>

Cas d'usage : Comprendre la reconciliation aide a ecrire du code performant et a bien utiliser les keys.

Anti-pattern : Changer le type d'un composant parent inutilement, forcant React a detruire tout le sous-arbre.
#core#interview#performance

Redux Toolkit

React 🟡 Mid

Boite a outils officielle de Redux qui simplifie la configuration du store, la creation de reducers et la gestion de la logique asynchrone.

Comme un kit de montage IKEA pour Redux : tout est pre-configure, plus besoin de 200 fichiers boilerplate.

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    add: (state, action) => { state.value += action.payload; }
  }
});

Cas d'usage : Etat global complexe necessitant de la predictibilite, du time-travel debugging et du middleware.

Anti-pattern : Mettre TOUT l'etat dans Redux y compris le state UI local (open/close modal).
#state#interview#ecosystem

Remix Conventions

React 🟡 Mid

Framework React full-stack qui embrasse les standards web (fetch, FormData, Response). Routes = fichiers, chaque route a loader/action/component co-localises.

Comme un restaurant local bio : il utilise les ingredients natifs (standards web) au lieu d'importer des produits exotiques.

// app/routes/users.tsx
export async function loader() {
  return json(await getUsers());
}
export async function action({ request }) {
  const form = await request.formData();
  return createUser(Object.fromEntries(form));
}
export default function Users() {
  const users = useLoaderData<typeof loader>();
}

Cas d'usage : Applications full-stack privilegiant les standards web, l'accessibilite et le progressive enhancement.

#framework#fullstack

Render Props

React 🟡 Mid

Pattern ou un composant recoit une fonction en prop qui retourne du JSX, permettant de partager de la logique tout en laissant le controle du rendu a l'appelant.

Comme un cours de peinture 'apporte ta toile' : le professeur (composant) guide, mais tu decides du resultat.

function MouseTracker({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  return (
    <div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>
      {render(pos)}
    </div>
  );
}
<MouseTracker render={({ x, y }) => <p>{x}, {y}</p>} />

Cas d'usage : Partager de la logique reutilisable entre composants (souvent remplace par les custom hooks aujourd'hui).

Anti-pattern : Imbriquer plusieurs render props creant un 'callback hell' illisible.
#patterns#interview

Route Groups

React 🟡 Mid

Dossiers parentheses (group) dans App Router qui organisent les routes sans affecter l'URL. Permettent des layouts differents pour des sections de l'app.

Comme des dossiers de classement invisibles : ils organisent les papiers mais ne changent pas l'adresse postale.

// app/(marketing)/about/page.tsx  -> /about
// app/(marketing)/layout.tsx      -> layout marketing
// app/(dashboard)/admin/page.tsx  -> /admin
// app/(dashboard)/layout.tsx      -> layout dashboard

Cas d'usage : Separer les layouts (public vs dashboard) ou organiser le code sans impacter les URLs.

#nextjs#routing

RTK Query

React 🟡 Mid

Solution de data fetching et caching integree a Redux Toolkit. Genere automatiquement les hooks, gere le cache, l'invalidation et les requetes optimistes.

Comme un assistant personnel qui passe les commandes, gere le stock et previent quand il faut reapprovisionner.

const api = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (build) => ({
    getUsers: build.query({ query: () => '/users' }),
    addUser: build.mutation({ query: (body) => ({ url: '/users', method: 'POST', body }) })
  })
});

Cas d'usage : Applications Redux avec beaucoup de data fetching, en alternative a React Query dans l'ecosysteme Redux.

#state#data-fetching

Server Actions

React 🟡 Mid

Fonctions asynchrones cote serveur invoquees directement depuis des composants client, typiquement via l'attribut action d'un formulaire. Remplacent les routes API manuelles.

Comme commander par telephone : tu passes l'ordre (client) et la cuisine (serveur) execute, sans aller au comptoir (API route).

// action.ts
'use server';
export async function addTodo(formData: FormData) {
  await db.todos.create({ text: formData.get('text') });
  revalidatePath('/todos');
}
// component.tsx
<form action={addTodo}><input name="text" /><button>Add</button></form>

Cas d'usage : Soumission de formulaires, CRUD, toute mutation serveur avec revalidation automatique.

#rendering#react19#nextjs

Server-side Validation

React 🟡 Mid

Validation des donnees cote serveur en complement du client, car la validation client est contournable. Avec Server Actions, le meme schema Zod peut valider des deux cotes.

Comme un double controle de securite : le portique (client) puis la fouille (serveur). Le portique seul ne suffit pas.

'use server';
const schema = z.object({ email: z.string().email() });

export async function createUser(formData: FormData) {
  const result = schema.safeParse(Object.fromEntries(formData));
  if (!result.success) return { errors: result.error.flatten() };
  await db.users.create(result.data);
}

Cas d'usage : Toute mutation de donnees : la validation client est UX, la validation serveur est securite.

Anti-pattern : Se reposer uniquement sur la validation client, exposant l'app a des donnees malformees.
#forms#security#bestpractice

Signals

React 🔴 Senior

Primitives reactives a grain fin qui mettent a jour le DOM directement sans re-rendu de composant. Popularises par Preact/SolidJS, en discussion pour React.

Comme un tableau d'affichage electronique : seule la case qui change se met a jour, pas tout le panneau.

// Avec @preact/signals-react
import { signal, computed } from '@preact/signals-react';

const count = signal(0);
const double = computed(() => count.value * 2);

function App() {
  return <p>{count} x 2 = {double}</p>;
}

Cas d'usage : Performance maximale avec des mises a jour granulaires sans reconciliation de tout le sous-arbre.

#state#advanced#future

Slot Pattern

React 🟡 Mid

Pattern qui permet au parent de passer du contenu JSX dans des emplacements nommes du composant enfant, via des props ou children specifiques.

Comme un formulaire administratif avec des cases a remplir : chaque case (slot) attend un contenu specifique.

function Layout({ header, sidebar, children }) {
  return (
    <div className="layout">
      <header>{header}</header>
      <aside>{sidebar}</aside>
      <main>{children}</main>
    </div>
  );
}
<Layout header={<Nav />} sidebar={<Menu />}>Contenu</Layout>

Cas d'usage : Composants de layout configurables avec plusieurs zones de contenu (header, footer, sidebar).

#patterns#composition

Les pages HTML sont generees au moment du build, pas a la requete. Resultat ultra-rapide puisque le CDN sert des fichiers statiques pre-generes.

Comme imprimer des flyers a l'avance : pas besoin de les creer a la demande, ils sont deja prets a distribuer.

// Next.js - page statique par defaut dans App Router
export default async function Blog() {
  const posts = await getPosts(); // execute au build
  return posts.map(p => <article key={p.id}>{p.title}</article>);
}
// export const dynamic = 'force-static';

Cas d'usage : Blogs, documentation, pages marketing dont le contenu ne change pas a chaque requete.

Anti-pattern : Utiliser SSG pour du contenu tres dynamique necessitant des rebuilds frequents.
#rendering#interview#performance

Le serveur genere le HTML complet a chaque requete. Le navigateur affiche la page immediatement puis l'hydrate avec React pour la rendre interactive.

Comme un plat prepare au restaurant (serveur) vs un kit a assembler chez soi (CSR) : le client recoit un plat deja pret.

// Next.js App Router
export default async function Page() {
  const data = await fetch('https://api.example.com/data');
  const posts = await data.json();
  return <PostList posts={posts} />;
}

Cas d'usage : Pages publiques necessitant un bon SEO et un premier affichage rapide (e-commerce, blogs, landing pages).

Anti-pattern : Faire du SSR pour des pages privees derriere authentification ou le SEO est inutile.
#rendering#interview#architecture

State

React 🟢 Junior

Donnees internes et mutables d'un composant. Quand le state change, React re-rend le composant pour refleter la nouvelle valeur.

Comme le score dans un jeu video : il change au fil du temps et l'affichage se met a jour automatiquement.

const [count, setCount] = useState(0);
return (
  <button onClick={() => setCount(c => c + 1)}>
    Clics: {count}
  </button>
);

Cas d'usage : Stocker des donnees dynamiques propres a un composant (formulaires, toggles, compteurs).

Anti-pattern : Muter le state directement (state.push()) au lieu d'utiliser le setter avec une nouvelle reference.
#core#interview#fundamentals

State Reducer Pattern

React 🔴 Senior

Pattern qui permet au consommateur d'un composant de personnaliser les transitions d'etat en fournissant son propre reducer, fusionnant avec le comportement par defaut.

Comme un pilote automatique avec override : l'avion vole seul mais le pilote peut reprendre le controle a tout moment.

function useToggle({ reducer = defaultReducer } = {}) {
  const [state, dispatch] = useReducer(reducer, { on: false });
  const toggle = () => dispatch({ type: 'TOGGLE' });
  return { ...state, toggle };
}
// L'utilisateur peut injecter son reducer custom
const { on, toggle } = useToggle({
  reducer: (state, action) => action.type === 'TOGGLE' && tooMany ? state : defaultReducer(state, action)
});

Cas d'usage : Librairies/composants generiques ou l'utilisateur doit pouvoir overrider le comportement interne.

#patterns#advanced

Storybook

React 🟡 Mid

Outil de developpement et documentation de composants UI en isolation. Chaque 'story' montre un etat du composant avec ses variantes.

Comme un catalogue IKEA : chaque meuble (composant) est photographie dans tous ses coloris et configurations.

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';

const meta: Meta<typeof Button> = { component: Button };
export default meta;

export const Primary: StoryObj = { args: { variant: 'primary', children: 'Click' } };
export const Disabled: StoryObj = { args: { disabled: true, children: 'Off' } };

Cas d'usage : Developper, tester visuellement et documenter les composants UI d'un design system.

#testing#documentation#design-system

Streaming SSR

React 🔴 Senior

Le serveur envoie le HTML en flux continu (stream) au lieu d'attendre que toute la page soit generee. Les parties lentes arrivent au fur et a mesure.

Comme regarder un match en streaming : tu vois l'action en direct au lieu d'attendre que l'enregistrement soit complet.

// Next.js App Router avec Suspense
export default function Page() {
  return (
    <main>
      <Header /> {/* envoye immediatement */}
      <Suspense fallback={<Skeleton />}>
        <SlowDataSection /> {/* stream quand pret */}
      </Suspense>
    </main>
  );
}

Cas d'usage : Pages avec des sections de vitesses differentes : le header s'affiche vite, les donnees arrivent en stream.

#rendering#performance#advanced

StrictMode

React 🟢 Junior

Composant de developpement qui active des verifications supplementaires et double les rendus pour detecter les effets de bord impurs.

Comme un professeur qui fait refaire l'exercice deux fois pour verifier que le resultat est toujours le meme.

<React.StrictMode>
  <App />
</React.StrictMode>
// En dev, useEffect s'execute 2 fois pour detecter les bugs

Cas d'usage : Activer en developpement pour detecter les effets de bord, les API depreciees et les problemes de cleanup.

#core#debugging

Suspense

React 🟡 Mid

Composant qui affiche un fallback pendant que ses enfants chargent des donnees ou du code asynchrone. Pilier du rendu concurrent.

Comme un ecran 'Chargement...' au cinema pendant que le projectionniste change de bobine.

const LazyPage = React.lazy(() => import('./Page'));

<Suspense fallback={<Spinner />}>
  <LazyPage />
</Suspense>

Cas d'usage : Afficher un loader pendant le chargement paresseux de composants ou de donnees avec React Query.

Anti-pattern : Entourer chaque composant avec Suspense individuellement au lieu de regrouper les limites logiques.
#core#interview#performance

SWR

React 🟡 Mid

Librairie de fetching de Vercel basee sur la strategie stale-while-revalidate : affiche les donnees en cache immediatement, puis revalide en arriere-plan.

Comme un journal du matin : tu lis celui d'hier (cache) en attendant que le facteur apporte le nouveau (revalidation).

import useSWR from 'swr';

const fetcher = (url) => fetch(url).then(r => r.json());

function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher);
  if (isLoading) return <Spinner />;
  return <p>{data.name}</p>;
}

Cas d'usage : Alternative plus legere a TanStack Query pour des cas de fetching simples.

#data-fetching#ecosystem

TanStack Query

React 🟡 Mid

Librairie de gestion de l'etat serveur (fetching, caching, synchronisation). Gere automatiquement le cache, la revalidation, le retry et les mises a jour optimistes.

Comme un concierge d'hotel : il anticipe tes besoins, garde tes affaires en cache et les rafraichit discretement.

const { data, isLoading } = useQuery({
  queryKey: ['users', userId],
  queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
  staleTime: 5 * 60 * 1000,
  gcTime: 10 * 60 * 1000,
});

Cas d'usage : Toute application qui consomme une API REST/GraphQL et a besoin de cache intelligent et de revalidation.

Anti-pattern : Stocker le resultat de useQuery dans un useState local, duplicant l'etat et perdant le cache.
#data-fetching#interview#ecosystem

use() Hook

React 🟡 Mid

Nouvelle API React 19 qui permet de lire une Promise ou un Context directement dans le rendu, meme de maniere conditionnelle contrairement aux autres hooks.

Comme un lecteur universel : qu'on lui donne un CD (Promise) ou une cle USB (Context), il lit les deux.

function UserProfile({ userPromise }) {
  const user = use(userPromise);
  return <p>{user.name}</p>;
}
// Peut etre utilise conditionnellement
if (showDetails) { const data = use(promise); }

Cas d'usage : Lire des donnees asynchrones dans les Server Components ou consommer un Context conditionnellement.

#hooks#react19

useCallback

React 🟡 Mid

Hook qui memoize une fonction pour conserver la meme reference entre les rendus. Equivalent a useMemo(() => fn, deps).

Comme donner toujours le meme numero de telephone a un contact : il n'a pas besoin de mettre a jour son carnet a chaque fois.

const handleClick = useCallback((id) => {
  setItems(prev => prev.filter(i => i.id !== id));
}, []); // reference stable

<MemoizedList onDelete={handleClick} />

Cas d'usage : Passer un callback a un composant enfant memoize avec React.memo pour eviter ses re-rendus inutiles.

Anti-pattern : Utiliser useCallback sans React.memo sur l'enfant : la memoisation ne sert alors a rien.
#hooks#interview#performance

useContext

React 🟢 Junior

Hook qui lit la valeur du Context le plus proche dans l'arbre. Evite le prop drilling en partageant des donnees entre composants distants.

Comme la radio FM : tout le monde dans la zone capte le meme signal sans cable direct.

const ThemeCtx = createContext('light');

function App() {
  return (
    <ThemeCtx.Provider value="dark">
      <Toolbar />
    </ThemeCtx.Provider>
  );
}
function Button() { const theme = useContext(ThemeCtx); }

Cas d'usage : Partager des donnees globales (theme, langue, user) sans passer par chaque niveau de props.

Anti-pattern : Mettre trop de donnees dans un seul contexte, causant des re-rendus inutiles de tous les consommateurs.
#hooks#interview#state

useDeferredValue

React 🟡 Mid

Hook qui retourne une version differee d'une valeur, permettant a React de prioriser les mises a jour urgentes et de differer le re-rendu du contenu non critique.

Comme un echo : ta voix (valeur originale) arrive d'abord, puis l'echo (valeur differee) suit avec un leger decalage.

const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);

// L'input reste reactif, la liste se met a jour en differe
<input value={query} onChange={e => setQuery(e.target.value)} />
<HeavyList filter={deferredQuery} />

Cas d'usage : Alternative a useTransition quand tu ne controles pas le setter de l'etat (props venant du parent).

Anti-pattern : Utiliser sur des valeurs primitives simples qui ne causent pas de rendu lourd.
#hooks#performance#react18

useEffect

React 🟢 Junior

Hook pour synchroniser un composant avec un systeme externe (API, DOM, timer). S'execute apres le rendu, avec un tableau de dependances pour controler quand il se relance.

Comme un abonnement a un journal : tu t'abonnes (setup), tu recois les numeros (re-runs), et tu te desabonnes (cleanup) en partant.

useEffect(() => {
  const ctrl = new AbortController();
  fetch('/api/data', { signal: ctrl.signal })
    .then(r => r.json())
    .then(setData);
  return () => ctrl.abort(); // cleanup
}, [userId]); // re-run si userId change

Cas d'usage : Appels API, abonnements WebSocket, synchronisation avec le DOM ou des librairies externes.

Anti-pattern : Omettre des dependances pour 'eviter les re-runs', causant des stale closures avec des valeurs perimees.
#hooks#interview#fundamentals

useFormStatus

React 🟡 Mid

Hook qui donne l'etat de soumission du formulaire parent (pending, data, method, action). Doit etre utilise dans un composant enfant du <form>.

Comme un indicateur lumineux sur une machine a cafe : il te dit si elle est en train de preparer (pending) ou prete.

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Envoi...' : 'Envoyer'}
    </button>
  );
}

Cas d'usage : Desactiver le bouton submit et afficher un spinner pendant la soumission d'un formulaire avec Server Actions.

Anti-pattern : Utiliser useFormStatus dans le meme composant que le <form> : il doit etre dans un enfant.
#hooks#react19#forms

useId

React 🟢 Junior

Hook qui genere un identifiant unique stable entre serveur et client, utile pour les attributs d'accessibilite comme htmlFor et aria-describedby.

Comme un tampon officiel : le meme numero est attribue que tu sois au guichet (serveur) ou en ligne (client).

function Input({ label }) {
  const id = useId();
  return (
    <>
      <label htmlFor={id}>{label}</label>
      <input id={id} />
    </>
  );
}

Cas d'usage : Generer des IDs pour les associations label/input sans risque de collision en SSR.

Anti-pattern : Utiliser useId pour generer des keys de liste : il n'est pas prevu pour ca.
#hooks#a11y#react18

useImperativeHandle

React 🟡 Mid

Hook qui personnalise la valeur exposee par un ref forwarde. Permet de n'exposer que certaines methodes d'un composant enfant au parent.

Comme un interphone d'immeuble : tu choisis quels boutons exposer, pas toutes les cles de l'appartement.

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
    clear: () => { inputRef.current.value = ''; }
  }));
  return <input ref={inputRef} />;
});

Cas d'usage : Exposer une API imperative limitee a un composant enfant (focus, scroll, reset).

Anti-pattern : Abuser de ce pattern pour recreer de la communication parent-enfant imperative au lieu du flux declaratif.
#hooks#advanced

useInsertionEffect

React 🔴 Senior

Hook qui s'execute avant toute mutation DOM, concu pour les librairies CSS-in-JS qui doivent injecter des balises <style> avant le layout.

Comme poser le papier peint avant d'installer les meubles : les styles sont prets avant que le DOM n'existe.

// Reserve aux auteurs de libs CSS-in-JS
useInsertionEffect(() => {
  const style = document.createElement('style');
  style.textContent = '.btn { color: red; }';
  document.head.appendChild(style);
  return () => style.remove();
}, []);

Cas d'usage : Exclusivement reserve aux librairies CSS-in-JS (styled-components, Emotion) pour injecter du CSS.

#hooks#advanced#css

useLayoutEffect

React 🟡 Mid

Identique a useEffect mais s'execute de maniere synchrone apres les mutations DOM et avant que le navigateur ne peigne. Bloque le rendu visuel.

Comme repositionner les meubles avant de prendre la photo : tout est en place avant que l'utilisateur ne voie.

useLayoutEffect(() => {
  const { height } = ref.current.getBoundingClientRect();
  setTooltipPos(height + 10);
}, []);

Cas d'usage : Mesurer le DOM (position, taille) ou corriger un layout avant l'affichage pour eviter un flash visuel.

Anti-pattern : Utiliser useLayoutEffect par defaut au lieu de useEffect, bloquant inutilement le rendu.
#hooks#performance#dom

useMemo

React 🟡 Mid

Hook qui memoize le resultat d'un calcul couteux et ne le recalcule que si ses dependances changent.

Comme mettre un plat au frigo : tu ne recuisines pas si les ingredients n'ont pas change, tu ressers le meme plat.

const sortedItems = useMemo(
  () => items.sort((a, b) => a.price - b.price),
  [items]
);
// Ne retrie que si 'items' change

Cas d'usage : Calculs couteux (tri, filtrage, transformations) qui ralentissent le rendu si recalcules a chaque fois.

Anti-pattern : Utiliser useMemo partout par defaut : le cout de la memoisation peut depasser celui du recalcul pour des operations simples.
#hooks#interview#performance

useOptimistic

React 🟡 Mid

Hook experimental qui permet d'afficher un etat optimiste pendant une action asynchrone, automatiquement annule en cas d'erreur.

Comme cocher 'lu' sur un message avant que le serveur confirme : si ca echoue, la coche disparait.

const [optimisticLikes, addOptimistic] = useOptimistic(
  likes,
  (state, newLike) => [...state, newLike]
);
async function handleLike() {
  addOptimistic({ id: 'temp', user: 'moi' });
  await saveLike();
}

Cas d'usage : Likes, commentaires, toggles : feedback instantane a l'utilisateur pendant la requete serveur.

#hooks#react19#ux

useReducer

React 🟡 Mid

Hook alternatif a useState pour gerer un etat complexe avec une logique de type action/reducer, inspire de Redux.

Comme un standard telephonique : tu envoies un message (action) et l'operateur (reducer) decide quoi faire.

const reducer = (state, action) => {
  switch(action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'reset': return { count: 0 };
    default: return state;
  }
};
const [state, dispatch] = useReducer(reducer, { count: 0 });

Cas d'usage : Etats complexes avec plusieurs sous-valeurs interdependantes ou quand la logique de transition est elaboree.

Anti-pattern : Utiliser useReducer pour un simple toggle booleen : useState est plus simple et lisible.
#hooks#interview#state

useRef

React 🟢 Junior

Hook qui retourne un objet mutable {current} persistant entre les rendus, sans declencher de re-rendu quand il change. Sert a referencer des elements DOM ou stocker des valeurs.

Comme un tiroir secret dans un bureau : tu y ranges des choses sans que personne ne le remarque (pas de re-rendu).

const inputRef = useRef(null);
const timerRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
  timerRef.current = setInterval(tick, 1000);
  return () => clearInterval(timerRef.current);
}, []);

Cas d'usage : Acceder au DOM (focus, scroll), stocker des IDs de timer, garder la valeur precedente d'un state.

Anti-pattern : Utiliser useRef pour stocker du state qui devrait declencher un re-rendu (utiliser useState a la place).
#hooks#interview#dom

useState

React 🟢 Junior

Hook qui ajoute un etat local a un composant fonctionnel. Retourne la valeur courante et une fonction pour la mettre a jour.

Comme un post-it sur le frigo : tu lis la valeur et tu la remplaces quand elle change.

const [name, setName] = useState('');

// Mise a jour fonctionnelle (recommandee)
setCount(prev => prev + 1);

// Initialisation couteuse avec lazy init
const [data, setData] = useState(() => expensiveCalc());

Cas d'usage : Tout etat local simple : champs de formulaire, toggles, compteurs, donnees UI.

Anti-pattern : Appeler le setter dans le corps du composant sans condition, causant une boucle infinie de re-rendus.
#hooks#interview#fundamentals

useSyncExternalStore

React 🔴 Senior

Hook pour s'abonner a un store externe (non-React) de maniere compatible avec le rendu concurrent, evitant les tearing (desynchro visuelle).

Comme un ecran d'aeroport synchronise : tous les passagers voient les memes horaires, pas de version perimee.

const width = useSyncExternalStore(
  (cb) => { window.addEventListener('resize', cb); return () => window.removeEventListener('resize', cb); },
  () => window.innerWidth,
  () => 1024 // server snapshot
);

Cas d'usage : Integration avec des stores externes (Zustand, Redux interne) ou des API navigateur (resize, online).

#hooks#advanced#react18

useTransition

React 🟡 Mid

Hook qui marque une mise a jour comme non urgente, permettant a React de la differer pour garder l'interface reactive pendant les operations lourdes.

Comme un panneau 'en cours de renovation' : les clients voient l'ancien decor pendant que tu renoves en arriere-plan.

const [isPending, startTransition] = useTransition();

function handleSearch(query) {
  startTransition(() => {
    setFilteredResults(heavyFilter(query));
  });
}
// isPending = true pendant le calcul

Cas d'usage : Filtrage de longues listes, navigation entre onglets, tout ce qui peut bloquer l'interface.

Anti-pattern : Envelopper des mises a jour urgentes (saisie de texte) dans startTransition, rendant l'input laggy.
#hooks#interview#performance#react18

Valtio

React 🟡 Mid

State management base sur des proxies JavaScript. L'etat est mutable directement et Valtio detecte les changements automatiquement via Proxy.

Comme un miroir magique : tu modifies l'objet original et le reflet (composant) se met a jour automatiquement.

const state = proxy({ count: 0, text: 'hello' });

function Counter() {
  const snap = useSnapshot(state);
  return (
    <button onClick={() => { state.count++; }}>
      {snap.count}
    </button>
  );
}

Cas d'usage : Developpeurs preferant la mutation directe d'objets, prototypage rapide, migration depuis MobX.

#state#ecosystem

Virtual DOM

React 🟢 Junior

Representation legere du DOM reel en memoire. React compare l'ancien et le nouveau Virtual DOM pour ne modifier que ce qui a change.

Comme un brouillon avant d'envoyer un email : tu fais tes corrections sur le brouillon, puis tu envoies seulement la version finale.

// React cree un arbre virtuel
// Ancien: <p>Bonjour</p>
// Nouveau: <p>Salut</p>
// React ne change que le texte du <p>, pas tout le DOM

Cas d'usage : Mecanisme interne qui optimise les mises a jour du DOM sans intervention manuelle.

Anti-pattern : Manipuler le DOM directement avec document.querySelector au lieu de laisser React gerer.
#core#interview#performance

Virtualization

React 🟡 Mid

Technique de rendu qui n'affiche que les elements visibles dans le viewport, meme pour des listes de milliers d'items. Les elements hors ecran ne sont pas montes.

Comme un ascenseur panoramique : tu ne vois que les etages devant toi, pas les 100 etages en meme temps.

import { useVirtualizer } from '@tanstack/react-virtual';

const virtualizer = useVirtualizer({
  count: 10000,
  getScrollElement: () => parentRef.current,
  estimateSize: () => 35,
});
// Ne rend que ~20 items visibles au lieu de 10000

Cas d'usage : Listes ou tableaux de plus de quelques centaines d'elements (logs, contacts, produits).

Anti-pattern : Virtualiser une liste de 20 elements : l'overhead de la virtualisation n'en vaut pas la peine.
#performance#interview

why-did-you-render

React 🟡 Mid

Librairie de debugging qui alerte dans la console quand un composant se re-rend inutilement (memes props mais nouvelle reference).

Comme un detecteur de fuite d'eau : il te montre exactement ou tu perds des performances.

// wdyr.js (importer en premier)
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
whyDidYouRender(React);

// Sur un composant specifique
MyComponent.whyDidYouRender = true;

Cas d'usage : Debugger les re-rendus excessifs pendant le developpement pour trouver les fuites de performance.

#performance#devtools#debugging

Zod + React Hook Form

React 🟡 Mid

Integration de Zod (validation de schemas) avec React Hook Form via @hookform/resolvers pour une validation typesafe partageable entre client et serveur.

Comme un contrat notarie pour un formulaire : les regles sont definies une fois et appliquees partout.

const schema = z.object({
  email: z.string().email('Email invalide'),
  age: z.number().min(18, 'Minimum 18 ans'),
});
type FormData = z.infer<typeof schema>;

const { register, handleSubmit } = useForm<FormData>({
  resolver: zodResolver(schema),
});

Cas d'usage : Formulaires avec validation complexe et types TypeScript inferes automatiquement depuis le schema.

#forms#typescript#validation

Zustand

React 🟡 Mid

Librairie de state management minimaliste sans boilerplate. Un store = une fonction, pas de Provider requis, compatible avec le rendu concurrent.

Comme un carnet de notes partage au bureau : tout le monde y accede directement, sans passer par un secretaire (Provider).

const useStore = create((set) => ({
  count: 0,
  increment: () => set((s) => ({ count: s.count + 1 })),
}));

function Counter() {
  const count = useStore((s) => s.count);
  return <span>{count}</span>;
}

Cas d'usage : Etat global simple a moyen sans la complexite de Redux, ideal pour les projets de toute taille.

Anti-pattern : Ne pas utiliser de selecteurs, souscrivant a tout le store et causant des re-rendus inutiles.
#state#interview#ecosystem

Autres stacks

Advanced Ecosystem Architecture CSS-in-JS DevOps HTML / CSS JavaScript MongoDB Mongoose NestJS Personalities PHP PostgreSQL Sass Styled-Components Tailwind CSS Testing TypeScript WordPress
← Retour au lexique complet