Notes pratiques : Les composants React doivent être purs — le secret derrière StrictMode
Guide pratique détaillé des notes pratiques : les composants React doivent être purs — le secret derrière StrictMode : contrats, vérifications et emplacements de code intégrable pour les équipes qui utilisent ce modèle.
Utilisez ceci comme une version révisée destinée aux opérateurs des idées présentées dans « React Components Must Be Pure — the Secret Behind StrictMode and the Compiler » : étapes claires, emplacements de code ordonnés et notes de récupération qui survivent au transfert de responsabilités. L’étape « Aperçu » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès et refusez toute complétion partielle silencieuse.
Qu’est-ce qu’une fonction pure ?
Pour l’étape « Qu’est-ce qu’une fonction pure ? », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût évite les factures inattendues lorsque le parcours passe d’un environnement de démonstration à des environnements partagés. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux temps d’exécution plus difficiles à détecter.
// ✅ pure function — same input, same output, and it touches nothing outside
function double(x: number): number {
return x * 2;
}
double(3); // 6
double(3); // 6 — six no matter how many times you call it
// 🔴 impure function — it changes the outer variable `total` (a side effect)
let total = 0;
function addToTotal(x: number): number {
total += x; // side effect!
return total; // the result changes on every call
}
addToTotal(3); // 3
addToTotal(3); // 6 — same input, different result
Un composant est aussi une fonction pure
Pour la composante A qui représente une étape, définissez les entrées, le responsable de cette étape ainsi que les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Placez l’état au même endroit que la composante responsable de la mutation. Mettre tout dans un stockage global rend plus difficiles à détecter les erreurs liées aux délais.
type Props = { name: string };
// ✅ pure — same name, always the same result
function Greeting({ name }: Props) {
return <h1>Hello, {name}!</h1>;
}
Enfreindre la règle — Ne pas toucher à l’extérieur pendant le rendu
Pour l’étape Break the Rule Don, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout en un stockage global rend les erreurs liées aux délais plus difficiles à détecter. Pour l’étape Break the Rule Don, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses.
let count = 0; // a variable outside the component
// 🔴 not pure — changes an external variable while rendering
function Counter() {
count = count + 1; // side effect!
return <p>{count}</p>;
}
Exécutez-le vous-même — Pourquoi apparaît le « 2 » ?
Lors de l’étape « Exécutez-le vous-même », notez d’abord les exigences : entrées requises, signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
import { useState } from 'react';
let count = 0;
function Counter() {
const [, setTick] = useState(0); // a device to trigger re-renders
count = count + 1; // 🔴 changes an external variable on every render
return (
<div>
<p>{count}</p>
<button onClick={() => setTick((n) => n + 1)}>Re-render</button>
</div>
);
}
// ✅ pure — computed from input (props) alone
function Counter({ count }: { count: number }) {
return <p>{count}</p>;
}
Mais vous pouvez modifier « Les éléments créés pendant le rendu »
Lorsque vous travaillez sur l’étape « But You Can Change », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
function ProductList({ products }: { products: Product[] }) {
// ✅ this array was just created in this render — handle it however you like
const sorted = [...products].sort((a, b) => a.price - b.price);
return (
<ul>
{sorted.map((p) => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
}
Le mystère 1 résolu — Pourquoi StrictMode exécute les opérations deux fois
Lors de la phase « Mystery 1 Solved Why », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’améliorations apportées ultérieurement. Considérez les effets secondaires comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu. Lors de la phase « Mystery 1 Solved Why », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des contrôles de succès et refusez les terminations partielles silencieuses.
// main.tsx — in development, the components inside this render twice
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
);
Où vont donc les effets secondaires ?
Les travaux en arrière-plan fonctionnent le mieux lorsqu’ils sont considérés comme une surface mesurable. Capturez un exemple réussi, un cas d’échec ainsi que la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Gardez les tâches de rendu peu coûteuses et reportez les calculs onéreux à la mise en mémoire après avoir effectué des mesures ; une mise en mémoire prématurée peut cacher des bugs liés à des données obsolètes.
// 🔴 side effect during rendering — fires on every render
function ProductPage({ id }: { id: number }) {
logView(id); // a side effect in the render body — not allowed
return <h1>Product {id}</h1>;
}
// ✅ in an event handler — runs only at the moment the user clicks
function BuyButton({ id }: { id: number }) {
return <button onClick={() => logPurchase(id)}>Buy</button>;
}
Mystère 2 résolu — Pourquoi le compilateur React repose sur la pureté
The Mystery 2 Solved : pourquoi l’interface fonctionne le mieux lorsqu’elle est traitée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec ainsi que la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Maintenez le coût des opérations de rendu faible et reportez les calculs coûteux à la mise en mémoire uniquement après avoir effectué des mesures. Une mise en mémoire prématurée peut cacher des erreurs liées à des données obsolètes.
// 🔴 not pure → the compiler skips optimization (ESLint points at this component)
let renderCount = 0;
function RenderCounter() {
renderCount++; // mutating an external variable during render — a violation
return <p>{renderCount}</p>;
}
// ✅ pure → the compiler memoizes automatically (reuse the previous result when inputs match)
function Label({ text }: { text: string }) {
return <p>{text}</p>;
}
function App() {
return (
<>
<RenderCounter />
<Label text="Pure Component" />
</>
);
}
export default App;
Voir l’UI comme un arbre
L’interface Seeing UI en tant qu’étape fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et le traitement des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Maintenez les coûts de rendu faibles et reportez les calculs coûteux à la mise en mémoire uniquement après avoir effectué des mesures. Une mise en mémoire prématurée peut cacher des bugs liés à des données obsolètes. L’interface Seeing UI en tant qu’étape fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des critères de succès et refusez toute complétion partielle silencieuse.
function App() {
return <ProductList products={products} />;
}
function ProductList({ products }: { products: Product[] }) {
return (
<ul>
{products.map((p) => (
<ProductCard key={p.id} product={p} />
))}
</ul>
);
}
App
└─ ProductList
├─ ProductCard
├─ ProductCard
└─ ProductCard
Conclusion
Pour l’étape de clôture, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût permet d’éviter des factures inattendues lorsque le parcours passe de l’environnement de démonstration à des environnements partagés. Placez l’état au même endroit que le composant responsable de la mutation ; placer tout dans un stockage global rend les erreurs liées aux temps d’exécution plus difficiles à détecter.
Références
Pour l’étape des références, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Placez l’état avec le composant qui gère la mutation. Mettre tout dans un stockage global rend les erreurs de synchronisation plus difficiles à détecter.
Liste de contrôle opérationnelle
Lorsque vous travaillez sur l’étape de la liste de contrôle opérationnelle, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste garantit que les modifications ultérieures du code restent transparentes.
Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité et non vers un processus embrouillé.
Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
Fixez les versions des dépendances et enregistrez le digest de l’image utilisée pour exécuter la démonstration. La reproductibilité vaut mieux que les connaissances propres à un groupe.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès, et refusez toute complétion partielle silencieuse.
Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
Au préalable de promouvoir l’ensemble technologique, figez les versions, conservez une transcription « or » pour le chemin critique, et vérifiez les étapes de rollback. Les environnements partagés nécessitent des limites de débit, des contrôles d’attribution, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité solide à des démonstrations brillantes mais ponctuelles.
Note de batch pour d707b555add8 : gardez les clés du fournisseur hors du répertoire, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers de configuration d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.