diff --git a/src/components/MDX/Sandpack/DownloadButton.tsx b/src/components/MDX/Sandpack/DownloadButton.tsx index 1a38d02de..14db56784 100644 --- a/src/components/MDX/Sandpack/DownloadButton.tsx +++ b/src/components/MDX/Sandpack/DownloadButton.tsx @@ -5,6 +5,7 @@ import {useSyncExternalStore} from 'react'; import {useSandpack} from '@codesandbox/sandpack-react/unstyled'; import {IconDownload} from '../../Icon/IconDownload'; +import {AppJSPath, StylesCSSPath, SUPPORTED_FILES} from './createFileMap'; export interface DownloadButtonProps {} let supportsImportMap = false; @@ -32,8 +33,6 @@ function useSupportsImportMap() { return useSyncExternalStore(subscribe, getCurrentValue, getServerSnapshot); } -const SUPPORTED_FILES = ['/App.js', '/styles.css']; - export function DownloadButton({ providedFiles, }: { @@ -49,8 +48,8 @@ export function DownloadButton({ } const downloadHTML = () => { - const css = sandpack.files['/styles.css']?.code ?? ''; - const code = sandpack.files['/App.js']?.code ?? ''; + const css = sandpack.files[StylesCSSPath]?.code ?? ''; + const code = sandpack.files[AppJSPath]?.code ?? ''; const blob = new Blob([ ` diff --git a/src/components/MDX/Sandpack/Preview.tsx b/src/components/MDX/Sandpack/Preview.tsx index 059645550..9669e5f4f 100644 --- a/src/components/MDX/Sandpack/Preview.tsx +++ b/src/components/MDX/Sandpack/Preview.tsx @@ -54,7 +54,7 @@ export function Preview({ // When throwing a new Error in Sandpack - we want to disable the dev error dialog // to show the Error Boundary fallback - if (rawError && rawError.message.includes(`throw Error('Example error')`)) { + if (rawError && rawError.message.includes('Example Error:')) { rawError = null; } diff --git a/src/components/MDX/Sandpack/SandpackRoot.tsx b/src/components/MDX/Sandpack/SandpackRoot.tsx index df0c757f2..d47fd903c 100644 --- a/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -9,6 +9,7 @@ import {SandpackLogLevel} from '@codesandbox/sandpack-client'; import {CustomPreset} from './CustomPreset'; import {createFileMap} from './createFileMap'; import {CustomTheme} from './Themes'; +import {template} from './template'; type SandpackProps = { children: React.ReactNode; @@ -70,17 +71,19 @@ function SandpackRoot(props: SandpackProps) { const codeSnippets = Children.toArray(children) as React.ReactElement[]; const files = createFileMap(codeSnippets); - files['/styles.css'] = { - code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), - hidden: !files['/styles.css']?.visible, + files['/src/styles.css'] = { + code: [sandboxStyle, files['/src/styles.css']?.code ?? ''].join('\n\n'), + hidden: !files['/src/styles.css']?.visible, }; return (
{ return codeSnippets.reduce( (result: Record, codeSnippet: React.ReactElement) => { @@ -26,15 +30,16 @@ export const createFileMap = (codeSnippets: any) => { } } else { if (props.className === 'language-js') { - filePath = '/App.js'; + filePath = AppJSPath; } else if (props.className === 'language-css') { - filePath = '/styles.css'; + filePath = StylesCSSPath; } else { throw new Error( `Code block is missing a filename: ${props.children}` ); } } + if (result[filePath]) { throw new Error( `File ${filePath} was defined multiple times. Each file snippet should have a unique path name` diff --git a/src/components/MDX/Sandpack/index.tsx b/src/components/MDX/Sandpack/index.tsx index 6873547a1..6755ba8de 100644 --- a/src/components/MDX/Sandpack/index.tsx +++ b/src/components/MDX/Sandpack/index.tsx @@ -3,7 +3,7 @@ */ import {lazy, memo, Children, Suspense} from 'react'; -import {createFileMap} from './createFileMap'; +import {AppJSPath, createFileMap} from './createFileMap'; const SandpackRoot = lazy(() => import('./SandpackRoot')); @@ -57,7 +57,7 @@ export default memo(function SandpackWrapper(props: any): any { ); let activeCode; if (!activeCodeSnippet.length) { - activeCode = codeSnippet['/App.js'].code; + activeCode = codeSnippet[AppJSPath].code; } else { activeCode = codeSnippet[activeCodeSnippet[0]].code; } diff --git a/src/components/MDX/Sandpack/template.ts b/src/components/MDX/Sandpack/template.ts new file mode 100644 index 000000000..e1169b7ae --- /dev/null +++ b/src/components/MDX/Sandpack/template.ts @@ -0,0 +1,54 @@ +export const template = { + '/src/index.js': { + hidden: true, + code: `import React, { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./styles.css"; + +import App from "./App"; + +const root = createRoot(document.getElementById("root")); +root.render( + + + +);`, + }, + '/package.json': { + hidden: true, + code: JSON.stringify( + { + name: 'react.dev', + version: '0.0.0', + main: '/src/index.js', + scripts: { + start: 'react-scripts start', + build: 'react-scripts build', + test: 'react-scripts test --env=jsdom', + eject: 'react-scripts eject', + }, + dependencies: { + react: '^18.0.0', + 'react-dom': '^18.0.0', + 'react-scripts': '^5.0.0', + }, + }, + null, + 2 + ), + }, + '/public/index.html': { + hidden: true, + code: ` + + + + + Document + + +
+ +`, + }, +}; diff --git a/src/components/Seo.tsx b/src/components/Seo.tsx index bb6c50ffd..aa983087a 100644 --- a/src/components/Seo.tsx +++ b/src/components/Seo.tsx @@ -24,6 +24,7 @@ const deployedTranslations = [ 'es', 'fr', 'ja', + 'tr', // We'll add more languages when they have enough content. // Please DO NOT edit this list without a discussion in the reactjs/react.dev repo. // It must be the same between all translations. diff --git a/src/content/blog/2022/03/08/react-18-upgrade-guide.md b/src/content/blog/2022/03/08/react-18-upgrade-guide.md index 74d3634cb..dc82efdcf 100644 --- a/src/content/blog/2022/03/08/react-18-upgrade-guide.md +++ b/src/content/blog/2022/03/08/react-18-upgrade-guide.md @@ -122,7 +122,7 @@ Pour en apprendre davantage, consultez [cette discussion du groupe de travail](h -**Si votre appli ne fonctionne plus après la migration, vérifiez si elle est enrobée par ``.** [Le mode strict est plus strict en React 18](#updates-to-strict-mode), et tous vos composants ne sont pas forcément conformes aux nouvelles vérifications qu'il effectue en mode développement. Si le retrait du mode strict fait refonctionner votre appli, vous pouvez le retirer pendant la migration puis le rajouter à la fin (soit à la racine soit sur une partie de l'arbre), après que vous aurez corrigé les problèmes qu'il met en lumière. +**Si votre appli ne fonctionne plus après la migration, vérifiez si elle est enrobée par ``.** [Le Mode Strict est plus strict en React 18](#updates-to-strict-mode), et tous vos composants ne sont pas forcément conformes aux nouvelles vérifications qu'il effectue en mode développement. Si le retrait du Mode Strict fait refonctionner votre appli, vous pouvez le retirer pendant la migration puis le rajouter à la fin (soit à la racine soit sur une partie de l'arbre), après que vous aurez corrigé les problèmes qu'il met en lumière. @@ -236,13 +236,13 @@ Au sein du groupe de travail React 18, nous avons collaboré avec des mainteneur React 18 ajoute également de nouvelles API pour le rendu concurrent telles que `startTransition`, `useDeferredValue` et `useId`, dont nous parlons plus en détail dans le [billet annonçant la sortie](/blog/2022/03/29/react-v18). -## Évolutions du mode strict {/*updates-to-strict-mode*/} +## Évolutions du Mode Strict {/*updates-to-strict-mode*/} À l'avenir, nous aimerions ajouter une fonctionnalité permettant à React d'ajouter ou de retirer des sections de l'UI tout en en préservant l'état. Lorsqu'un utilisateur clique par exemple sur un nouvel onglet pour revenir ensuite sur celui qui était actif auparavant, React devrait pouvoir en restaurer l'état. Pour y parvenir, React démonterait et remonterait ces arbres en utilisant le même état de composant. Cette fonctionnalité améliorerait d'office les performances des applis React, mais exigerait que les Effets des composants résistent bien à des cycles multiples de démontage + remontage. La plupart des Effets fonctionneront sans modification, mais il peut arriver que le code de certains Effets suppose qu'ils ne seront montés ou démontés qu'une seule fois. -Pour vous aider à débusquer ces soucis, React 18 ajoute une nouvelle vérification en mode développement uniquement dans le mode strict. Elle démonte et remonte automatiquement chaque composant, lorsqu'un composant est monté pour la première fois, et restaure l'état précédent au second montage. +Pour vous aider à débusquer ces soucis, React 18 ajoute une nouvelle vérification en mode développement uniquement dans le Mode Strict. Elle démonte et remonte automatiquement chaque composant, lorsqu'un composant est monté pour la première fois, et restaure l'état précédent au second montage. Avant cet ajustement, React montait le composant et instanciait ses Effets : @@ -252,7 +252,7 @@ Avant cet ajustement, React montait le composant et instanciait ses Effets : * Les Effets sont créés. ``` -Avec le mode strict de React 18, React simule ensuite, en mode développement, le démontage et le remontage du composant : +Avec le Mode Strict de React 18, React simule ensuite, en mode développement, le démontage et le remontage du composant : ``` * React monte le composant. @@ -266,7 +266,7 @@ Avec le mode strict de React 18, React simule ensuite, en mode développement, l * Les Effets sont créés. ``` -Pour en apprendre davantage, consultez les discussions du groupe de travail sur [l'ajout d'un état réutilisable au mode strict](https://github.com/reactwg/react-18/discussions/19) et [comment prendre en charge un état réutilisable dans les Effets](https://github.com/reactwg/react-18/discussions/18). +Pour en apprendre davantage, consultez les discussions du groupe de travail sur [l'ajout d'un état réutilisable au Mode Strict](https://github.com/reactwg/react-18/discussions/19) et [comment prendre en charge un état réutilisable dans les Effets](https://github.com/reactwg/react-18/discussions/18). ## Configurer votre environnement de test {/*configuring-your-testing-environment*/} @@ -324,7 +324,7 @@ Si vous devez encore prendre en charge Internet Explorer, nous vous conseillons * **Les composants peuvent désormais produire `undefined`** : React ne vous avertira plus si vous renvoyez `undefined` depuis un composant. Ça apporte de la cohérence entre les valeurs renvoyées autorisées et celles permises au sein d'un arbre de composants. Nous vous suggérons d'utiliser une règle d'analyse statique (*linter*) pour éviter d'oublier un `return` devant votre JSX. * **Les avertissements sur `act` dans les tests sont désormais optionnels** : si vous exécutez des tests de bout en bout *(end-to-end, NdT)*, les avertissements sur `act` sont superflus. Nous avons ajouté un mécanisme d'activation [sur demande](https://github.com/reactwg/react-18/discussions/102) pour que vous puissiez ne les activer que dans des tests unitaires, pour lesquels ils sont effectivement utiles. * **Fin de l'avertissement sur `setState` dans les composants démontés** : jusqu'ici React vous avertissait de fuites de mémoire potentielles lorsque vous appeliez `setState` sur un composant démonté. Cet avertissement avait été ajouté par rapport aux abonnements, mais la plupart des gens le rencontraient plutôt dans des scénarios où la modification de l'état était acceptable, et les solutions de contournement ne faisaient qu'empirer les choses. Nous avons [retiré](https://github.com/facebook/react/pull/22114) cet avertissement. -* **Arrêt de la censure des affichages en console** : lorsque vous utilisez le mode strict, React fait un double rendu de chaque composant pour vous aider à repérer des effets de bord inattendus. Dans React 17, nous censurions les affichages en console de l'un des deux rendus pour faciliter la lecture des journaux. Mais suite aux [retours de la communauté](https://github.com/facebook/react/issues/21783) sur la confusion que ça entraînait, nous avons cessé d'occulter ces messages. Si vous avez les outils de développement React installés, vous y verrez plutôt le deuxième jeu de messages apparaître grisé, et une option (inactive par défaut) permet de les retirer complètement. +* **Arrêt de la censure des affichages en console** : lorsque vous utilisez le Mode Strict, React fait un double rendu de chaque composant pour vous aider à repérer des effets de bord inattendus. Dans React 17, nous censurions les affichages en console de l'un des deux rendus pour faciliter la lecture des journaux. Mais suite aux [retours de la communauté](https://github.com/facebook/react/issues/21783) sur la confusion que ça entraînait, nous avons cessé d'occulter ces messages. Si vous avez les outils de développement React installés, vous y verrez plutôt le deuxième jeu de messages apparaître grisé, et une option (inactive par défaut) permet de les retirer complètement. * **Consommation mémoire améliorée** : React nettoie désormais davantage de champs internes au démontage, réduisant ainsi l'impact de fuites de mémoires éventuelles dans votre application. ### React DOM (Côté serveur) {/*react-dom-server*/} diff --git a/src/content/blog/2022/03/29/react-v18.md b/src/content/blog/2022/03/29/react-v18.md index 7e03fbd30..98250105d 100644 --- a/src/content/blog/2022/03/29/react-v18.md +++ b/src/content/blog/2022/03/29/react-v18.md @@ -58,7 +58,7 @@ Techniquement, le rendu concurrent constitue une rupture de compatibilité ascen Pour nos tests, nous avons migré des milliers de composants sur React 18. Nous avons constaté que presque tous les composants existants continuent à marcher avec le rendu concurrent, sans rien avoir besoin d'y changer. Cependant, certains d'entre eux risquent de nécessiter un effort supplémentaire de migration. Même si ces changements sont généralement mineurs, vous pourrez quand même les apporter à votre rythme. Le nouveau comportement de rendu de React 18 **n'est activé que dans les parties de votre appli qui utilisent les nouvelles fonctionnalités**. -La stratégie générale de mise à jour consiste à faire tourner votre application avec React 18 sans casser le code existant. Vous pouvez alors commencer à ajouter graduellement des fonctionnalités concurrentes, à votre rythme. Vous pouvez utiliser [``](/reference/react/StrictMode) pour vous aider à faire émerger des bugs liés à la concurrence lors du développement. Le mode strict n'a aucun impact sur le comportement en production, mais lors du développement il affichera en console des avertissements supplémentaires, et fera des invocations doubles de fonctions censées être idempotentes (pures). Ça n'attrapera pas tout, mais ça reste un moyen efficace d'éviter les principaux types d'erreurs. +La stratégie générale de mise à jour consiste à faire tourner votre application avec React 18 sans casser le code existant. Vous pouvez alors commencer à ajouter graduellement des fonctionnalités concurrentes, à votre rythme. Vous pouvez utiliser [``](/reference/react/StrictMode) pour vous aider à faire émerger des bugs liés à la concurrence lors du développement. Le Mode Strict n'a aucun impact sur le comportement en production, mais lors du développement il affichera en console des avertissements supplémentaires, et fera des invocations doubles de fonctions censées être idempotentes (pures). Ça n'attrapera pas tout, mais ça reste un moyen efficace d'éviter les principaux types d'erreurs. Après que vous aurez migré sur React 18, vous pourrez commencer à utiliser les fonctionnalités concurrentes immédiatement. Vous pourrez par exemple utiliser `startTransition` pour naviguer entre les écrans sans bloquer la saisie utilisateur. Ou `useDeferredValue` pour minimiser le nombre de rendus coûteux. @@ -191,13 +191,13 @@ La méthode `renderToString` existante reste disponible, mais elle est désormai [Consultez la documentation de React DOM côté serveur](/reference/react-dom/server). -### Nouveaux comportements du mode strict {/*new-strict-mode-behaviors*/} +### Nouveaux comportements du Mode Strict {/*new-strict-mode-behaviors*/} À l'avenir, nous aimerions ajouter une fonctionnalité permettant à React d'ajouter ou de retirer des sections de l'UI tout en en préservant l'état. Lorsqu'un utilisateur clique par exemple sur un nouvel onglet pour revenir ensuite sur celui qui était actif auparavant, React devrait pouvoir en restaurer l'état. Pour y parvenir, React démonterait et remonterait ces arbres en utilisant le même état de composant. Cette fonctionnalité améliorerait d'office les performances des applis React, mais exigerait que les Effets des composants résistent bien à des cycles multiples de démontage + remontage. La plupart des Effets fonctionneront sans modification, mais il peut arriver que le code de certains Effets suppose qu'ils ne seront montés ou démontés qu'une seule fois. -Pour vous aider à débusquer ces soucis, React 18 ajoute une nouvelle vérification en mode développement uniquement dans le mode strict. Elle démonte et remonte automatiquement chaque composant, lorsqu'un composant est monté pour la première fois, et restaure l'état précédent au second montage. +Pour vous aider à débusquer ces soucis, React 18 ajoute une nouvelle vérification en mode développement uniquement dans le Mode Strict. Elle démonte et remonte automatiquement chaque composant, lorsqu'un composant est monté pour la première fois, et restaure l'état précédent au second montage. Avant cet ajustement, React montait le composant et instanciait ses Effets : @@ -207,7 +207,7 @@ Avant cet ajustement, React montait le composant et instanciait ses Effets : * Les Effets sont créés. ``` -Avec le mode strict de React 18, React simule ensuite, en mode développement, le démontage et le remontage du composant : +Avec le Mode Strict de React 18, React simule ensuite, en mode développement, le démontage et le remontage du composant : ``` * React monte le composant. @@ -221,7 +221,7 @@ Avec le mode strict de React 18, React simule ensuite, en mode développement, l * Les Effets sont créés. ``` -[En apprendre davantage sur ce comportement du mode strict](/reference/react/StrictMode#fixing-bugs-found-by-re-running-effects-in-development). +[En apprendre davantage sur ce comportement du Mode Strict](/reference/react/StrictMode#fixing-bugs-found-by-re-running-effects-in-development). ### Nouveaux Hooks {/*new-hooks*/} diff --git a/src/content/blog/2023/03/16/introducing-react-dev.md b/src/content/blog/2023/03/16/introducing-react-dev.md index 47b66eabb..b42cc9877 100644 --- a/src/content/blog/2023/03/16/introducing-react-dev.md +++ b/src/content/blog/2023/03/16/introducing-react-dev.md @@ -58,7 +58,7 @@ Si vous aimez apprendre en pratiquant, nous vous recommandons de continuer avec -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -176,7 +176,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -429,7 +429,7 @@ export default function PackingList() { Remarquez qu'il faut écrire `importance > 0 && ...` plutôt que juste `importance && ...` afin de nous assurer que si `importance` vaut `0`, `0` ne sera pas affiché comme résultat ! -Dans cette solution, on utilise deux conditions distinctes pour insérer une espace entre le nom et le libellé d'importance. On aurait aussi pu utiliser un fragment avec une espace au début : `importance > 0 && <> ...` ou ajouter l'espace immédiatement au début du `` : `importance > 0 && ...`. +Dans cette solution, on utilise deux conditions distinctes pour insérer une espace entre le nom et le libellé d'importance. On aurait aussi pu utiliser un Fragment avec une espace au début : `importance > 0 && <> ...` ou ajouter l'espace immédiatement au début du `` : `importance > 0 && ...`. @@ -441,7 +441,6 @@ Remarquez le bouton « Afficher la solution » dans le coin inférieur gauche. Lorsqu'on ne trouvait pas une bonne manière d'expliquer quelque chose juste avec du code et des mots, on a ajouté des diagrammes pour vous aider à bâtir votre intuition. Voici par exemple un des diagrammes de [Préserver et réinitialiser l'état](/learn/preserving-and-resetting-state) : - Quand la `section` change pour un `div`, la `section` est supprimée est le nouveau `div` est ajouté diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index ae437beb2..7b4142e7d 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -10,72 +10,77 @@ Vous connaissez une conférence React.js locale ? Ajoutez-la ! (Merci de conse ## Conférences à venir {/*upcoming-conferences*/} -### RedwoodJS Conference 2023 {/*redwoodjs-conference-2023*/} -September 26 - 29, 2023. Grants Pass, Oregon + remote (hybrid event) - -[Site web](https://www.redwoodjsconf.com/) - [Twitter](https://twitter.com/redwoodjs) +### App.js Conf 2024 {/*appjs-conf-2024*/} +May 22 - 24, 2024. In-person in Kraków, Poland + remote -### React Alicante 2023 {/*react-alicante-2023*/} -September 28 - 30, 2023. Alicante, Spain +[Site web](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) -[Site web](https://reactalicante.es/) - [Twitter](https://twitter.com/reactalicante) +### Render(ATL) 2024 🍑 {/*renderatl-2024-*/} +June 12 - June 14, 2024. Atlanta, GA, USA -### React Live 2023 {/*react-live-2023*/} -September 29, 2023. Amsterdam, Netherlands +[Site web](https://renderatl.com) - [Discord](https://www.renderatl.com/discord) - [Twitter](https://twitter.com/renderATL) - [Instagram](https://www.instagram.com/renderatl/) - [Facebook](https://www.facebook.com/renderatl/) - [LinkedIn](https://www.linkedin.com/company/renderatl) - [Podcast](https://www.renderatl.com/culture-and-code#/) -[Site web](https://reactlive.nl/) +### React India 2024 {/*react-india-2024*/} +October 17 - 19, 2024. In-person in Goa, India (hybrid event) + Oct 15 2024 - remote day -### React Native EU 2023 {/*react-native-eu-2023*/} -September 7 & 8, 2023. Wrocław, Poland +[Site web](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) -[Site web](https://react-native.eu) - [Twitter](https://twitter.com/react_native_eu) - [Facebook](https://www.facebook.com/reactnativeeu) +## Conférences passées {/*past-conferences*/} -### RenderCon Kenya 2023 {/*rendercon-kenya-2023*/} -September 29 - 30, 2023. Nairobi, Kenya +### React Day Berlin 2023 {/*react-day-berlin-2023*/} +December 8 & 12, 2023. In-person in Berlin, Germany + remote first interactivity (hybrid event) -[Site web](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA) +[Site web](https://reactday.berlin) - [Twitter](https://twitter.com/reactdayberlin) - [Facebook](https://www.facebook.com/reactdayberlin/) - [Vidéos](https://portal.gitnation.org/events/react-day-berlin-2023) -### React India 2023 {/*react-india-2023*/} -October 5 - 7, 2023. In-person in Goa, India (hybrid event) + Oct 3 2023 - remote day +### React Summit US 2023 {/*react-summit-us-2023*/} +November 13 & 15, 2023. In-person in New York, US + remote first interactivity (hybrid event) -[Site web](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) +[Site web](https://reactsummit.us) - [Twitter](https://twitter.com/reactsummit) - [Facebook](https://www.facebook.com/reactamsterdam) - [Vidéos](https://portal.gitnation.org/events/react-summit-us-2023) -### React Brussels 2023 {/*react-brussels-2023*/} -October 13th 2023. In-person in Brussels, Belgium + Remote (hybrid) +### reactjsday 2023 {/*reactjsday-2023*/} +October 27th 2023. In-person in Verona, Italy and online (hybrid event) -[Site web](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact) +[Site web](https://2023.reactjsday.it/) - [Twitter](https://twitter.com/reactjsday) - [Facebook](https://www.facebook.com/GrUSP/) - [YouTube](https://www.youtube.com/c/grusp) ### React Advanced 2023 {/*react-advanced-2023*/} October 20 & 23, 2023. In-person in London, UK + remote first interactivity (hybrid event) [Site web](https://www.reactadvanced.com/) - [Twitter](https://twitter.com/ReactAdvanced) - [Facebook](https://www.facebook.com/ReactAdvanced) - [Vidéos](https://portal.gitnation.org/events/react-advanced-conference-2023) -### reactjsday 2023 {/*reactjsday-2023*/} -October 27th 2023. In-person in Verona, Italy and online (hybrid event) +### React Brussels 2023 {/*react-brussels-2023*/} +October 13th 2023. In-person in Brussels, Belgium + Remote (hybrid) -[Site web](https://2023.reactjsday.it/) - [Twitter](https://twitter.com/reactjsday) - [Facebook](https://www.facebook.com/GrUSP/) - [YouTube](https://www.youtube.com/c/grusp) +[Site web](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact) -### React Summit US 2023 {/*react-summit-us-2023*/} -November 13 & 15, 2023. In-person in New York, US + remote first interactivity (hybrid event) +### React India 2023 {/*react-india-2023*/} +October 5 - 7, 2023. In-person in Goa, India (hybrid event) + Oct 3 2023 - remote day -[Site web](https://reactsummit.us) - [Twitter](https://twitter.com/reactsummit) - [Facebook](https://www.facebook.com/reactamsterdam) - [Vidéos](https://portal.gitnation.org/events/react-summit-us-2023) +[Site web](https://www.reactindia.io) - [Twitter](https://x.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) -### React Day Berlin 2023 {/*react-day-berlin-2023*/} -December 8 & 12, 2023. In-person in Berlin, Germany + remote first interactivity (hybrid event) +### RenderCon Kenya 2023 {/*rendercon-kenya-2023*/} +September 29 - 30, 2023. Nairobi, Kenya -[Site web](https://reactday.berlin) - [Twitter](https://twitter.com/reactdayberlin) - [Facebook](https://www.facebook.com/reactdayberlin/) - [Vidéos](https://portal.gitnation.org/events/react-day-berlin-2023) +[Site web](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA) -### App.js Conf 2024 {/*appjs-conf-2024*/} -May 22 - 24, 2024. In-person in Kraków, Poland + remote +### React Live 2023 {/*react-live-2023*/} +September 29, 2023. Amsterdam, Netherlands -[Site web](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) +[Site web](https://reactlive.nl/) -### Render(ATL) 2024 🍑 {/*renderatl-2024-*/} -June 12 - June 14, 2024. Atlanta, GA, USA +### React Alicante 2023 {/*react-alicante-2023*/} +September 28 - 30, 2023. Alicante, Spain -[Site web](https://renderatl.com) - [Discord](https://www.renderatl.com/discord) - [Twitter](https://twitter.com/renderATL) - [Instagram](https://www.instagram.com/renderatl/) - [Facebook](https://www.facebook.com/renderatl/) - [LinkedIn](https://www.linkedin.com/company/renderatl) - [Podcast](https://www.renderatl.com/culture-and-code#/) +[Site web](https://reactalicante.es/) - [Twitter](https://twitter.com/reactalicante) -## Conférences passées {/*past-conferences*/} +### RedwoodJS Conference 2023 {/*redwoodjs-conference-2023*/} +September 26 - 29, 2023. Grants Pass, Oregon + remote (hybrid event) + +[Site web](https://www.redwoodjsconf.com/) - [Twitter](https://twitter.com/redwoodjs) + +### React Native EU 2023 {/*react-native-eu-2023*/} +September 7 & 8, 2023. Wrocław, Poland + +[Site web](https://react-native.eu) - [Twitter](https://twitter.com/react_native_eu) - [Facebook](https://www.facebook.com/reactnativeeu) ### React Rally 2023 🐙 {/*react-rally-2023*/} August 17 & 18, 2023. Salt Lake City, UT, USA diff --git a/src/content/community/meetups.md b/src/content/community/meetups.md index 5977d3fed..ddc71e0b5 100644 --- a/src/content/community/meetups.md +++ b/src/content/community/meetups.md @@ -155,6 +155,7 @@ Vous connaissez un meetup React.js local ? Ajoutez-le ! (Merci de conserver un * [Bangalore (React Native)](https://www.meetup.com/React-Native-Bangalore-Meetup) * [Chennai](https://www.meetup.com/React-Chennai/) * [Delhi NCR](https://www.meetup.com/React-Delhi-NCR/) +* [Mumbai](https://reactmumbai.dev) * [Pune](https://www.meetup.com/ReactJS-and-Friends/) ## Indonésie {/*indonesia*/} diff --git a/src/content/learn/add-react-to-an-existing-project.md b/src/content/learn/add-react-to-an-existing-project.md index 668b58fdd..8afc2e747 100644 --- a/src/content/learn/add-react-to-an-existing-project.md +++ b/src/content/learn/add-react-to-an-existing-project.md @@ -67,7 +67,7 @@ Ensuite, ajoutez ces lignes de code en haut de votre fichier JavaScript principa ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; // Effacez le contenu HTML existant @@ -131,7 +131,7 @@ Vous souhaitez probablement plutôt afficher vos composants React à des emplace ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; function NavigationBar() { diff --git a/src/content/learn/adding-interactivity.md b/src/content/learn/adding-interactivity.md index a542d291b..64b4deb22 100644 --- a/src/content/learn/adding-interactivity.md +++ b/src/content/learn/adding-interactivity.md @@ -134,7 +134,7 @@ export default function Gallery() { } ``` -```js data.js +```js src/data.js export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md index 99bd25a7c..df7f490fd 100644 --- a/src/content/learn/choosing-the-state-structure.md +++ b/src/content/learn/choosing-the-state-structure.md @@ -616,7 +616,7 @@ export default function TravelPlan() { } ``` -```js places.js active +```js src/places.js active export const initialTravelPlan = { id: 0, title: '(Root)', @@ -871,7 +871,7 @@ export default function TravelPlan() { } ``` -```js places.js active +```js src/places.js active export const initialTravelPlan = { 0: { id: 0, @@ -1207,7 +1207,7 @@ function PlaceTree({ id, parentId, placesById, onComplete }) { } ``` -```js places.js +```js src/places.js export const initialTravelPlan = { 0: { id: 0, @@ -1546,7 +1546,7 @@ function PlaceTree({ id, parentId, placesById, onComplete }) { } ``` -```js places.js +```js src/places.js export const initialTravelPlan = { 0: { id: 0, @@ -1844,7 +1844,7 @@ Ce composant `Clock` reçoit deux props : `color` et `time`. Lorsque vous séle -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock(props) { @@ -1857,7 +1857,7 @@ export default function Clock(props) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -1899,7 +1899,7 @@ Le problème, c'est que ce composant a un état `color` initialisé avec la vale -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock(props) { @@ -1911,7 +1911,7 @@ export default function Clock(props) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -1951,7 +1951,7 @@ Ou en utilisant la syntaxe de déstructuration : -```js Clock.js active +```js src/Clock.js active import { useState } from 'react'; export default function Clock({ color, time }) { @@ -1963,7 +1963,7 @@ export default function Clock({ color, time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -2013,7 +2013,7 @@ Y a-t-il un état redondant dans cet exemple ? -```js App.js +```js src/App.js import { useState } from 'react'; import AddItem from './AddItem.js'; import PackingList from './PackingList.js'; @@ -2081,7 +2081,7 @@ export default function TravelPlan() { } ``` -```js AddItem.js hidden +```js src/AddItem.js hidden import { useState } from 'react'; export default function AddItem({ onAddItem }) { @@ -2102,7 +2102,7 @@ export default function AddItem({ onAddItem }) { } ``` -```js PackingList.js hidden +```js src/PackingList.js hidden import { useState } from 'react'; export default function PackingList({ @@ -2152,7 +2152,7 @@ Bien que vous puissiez modifier soigneusement chaque gestionnaire d'événement -```js App.js +```js src/App.js import { useState } from 'react'; import AddItem from './AddItem.js'; import PackingList from './PackingList.js'; @@ -2216,7 +2216,7 @@ export default function TravelPlan() { } ``` -```js AddItem.js hidden +```js src/AddItem.js hidden import { useState } from 'react'; export default function AddItem({ onAddItem }) { @@ -2237,7 +2237,7 @@ export default function AddItem({ onAddItem }) { } ``` -```js PackingList.js hidden +```js src/PackingList.js hidden import { useState } from 'react'; export default function PackingList({ @@ -2293,7 +2293,7 @@ Ce code fonctionne, mais il y a un bug mineur d’UI. Quand vous appuyez sur « -```js App.js +```js src/App.js import { useState } from 'react'; import { initialLetters } from './data.js'; import Letter from './Letter.js'; @@ -2340,7 +2340,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, isHighlighted, @@ -2370,7 +2370,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const initialLetters = [{ id: 0, subject: 'Prêt pour l’aventure ?', @@ -2402,7 +2402,7 @@ Pour résoudre ce problème, supprimez la duplication de l’état. Au lieu de s -```js App.js +```js src/App.js import { useState } from 'react'; import { initialLetters } from './data.js'; import Letter from './Letter.js'; @@ -2449,7 +2449,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, isHighlighted, @@ -2479,7 +2479,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const initialLetters = [{ id: 0, subject: 'Prêt pour l’aventure ?', @@ -2519,7 +2519,7 @@ Au lieu d’un simple ID sélectionné, vous voulez plutôt enregistrer une list -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2562,7 +2562,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2587,7 +2587,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Prêt pour l’aventure ?', @@ -2618,7 +2618,7 @@ Au lieu d’un simple `selectedId`, enregistrez une *liste* `selectedIds` dans l -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2670,7 +2670,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2695,7 +2695,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Prêt pour l’aventure ?', @@ -2726,7 +2726,7 @@ Pour résoudre ce problème, vous pouvez plutôt utiliser un [Set](https://devel -```js App.js +```js src/App.js import { useState } from 'react'; import { letters } from './data.js'; import Letter from './Letter.js'; @@ -2775,7 +2775,7 @@ export default function MailClient() { } ``` -```js Letter.js +```js src/Letter.js export default function Letter({ letter, onToggle, @@ -2800,7 +2800,7 @@ export default function Letter({ } ``` -```js data.js +```js src/data.js export const letters = [{ id: 0, subject: 'Prêt pour l’aventure ?', diff --git a/src/content/learn/conditional-rendering.md b/src/content/learn/conditional-rendering.md index bcc33006c..8006ba458 100644 --- a/src/content/learn/conditional-rendering.md +++ b/src/content/learn/conditional-rendering.md @@ -624,7 +624,7 @@ export default function PackingList() { Remarquez qu'il faut écrire `importance > 0 && ...` plutôt que juste `importance && ...` afin de nous assurer que si `importance` vaut `0`, `0` ne sera pas affiché comme résultat ! -Dans cette solution, on utilise deux conditions distinctes pour insérer une espace entre le nom et le libellé d'importance. On aurait aussi pu utiliser un fragment avec une espace au début : `importance > 0 && <> ...` ou ajouter l'espace immédiatement au début du `` : `importance > 0 && ...`. +Dans cette solution, on utilise deux conditions distinctes pour insérer une espace entre le nom et le libellé d'importance. On aurait aussi pu utiliser un Fragment avec une espace au début : `importance > 0 && <> ...` ou ajouter l'espace immédiatement au début du `` : `importance > 0 && ...`. diff --git a/src/content/learn/describing-the-ui.md b/src/content/learn/describing-the-ui.md index ed9d1a4c7..53a4cd10c 100644 --- a/src/content/learn/describing-the-ui.md +++ b/src/content/learn/describing-the-ui.md @@ -68,7 +68,7 @@ Vous pouvez déclarer plusieurs composants dans un même fichier, mais les fichi -```js App.js hidden +```js src/App.js hidden import Gallery from './Gallery.js'; export default function App() { @@ -78,7 +78,7 @@ export default function App() { } ``` -```js Gallery.js active +```js src/Gallery.js active import Profile from './Profile.js'; export default function Gallery() { @@ -93,7 +93,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export default function Profile() { return ( -```js App.js +```js src/App.js import { people } from './data.js'; import { getImageUrl } from './utils.js'; @@ -397,7 +397,7 @@ export default function List() { } ``` -```js data.js +```js src/data.js export const people = [{ id: 0, name: 'Creola Katherine Johnson', @@ -431,7 +431,7 @@ export const people = [{ }]; ``` -```js utils.js +```js src/utils.js export function getImageUrl(person) { return ( 'https://i.imgur.com/' + diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md index 14c9fdf8a..9075d3ccb 100644 --- a/src/content/learn/escape-hatches.md +++ b/src/content/learn/escape-hatches.md @@ -163,7 +163,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js export function createConnection() { // Une véritable implémentation se connecterait en vrai return { @@ -282,7 +282,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -396,7 +396,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur let connectedCallback; @@ -425,7 +425,7 @@ export function createConnection(serverUrl, roomId) { } ``` -```js notifications.js +```js src/notifications.js import Toastify from 'toastify-js'; import 'toastify-js/src/toastify.css'; @@ -529,7 +529,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur let connectedCallback; @@ -558,7 +558,7 @@ export function createConnection(serverUrl, roomId) { } ``` -```js notifications.js hidden +```js src/notifications.js hidden import Toastify from 'toastify-js'; import 'toastify-js/src/toastify.css'; @@ -648,7 +648,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -722,7 +722,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -798,7 +798,7 @@ function Dot({ position, opacity }) { } ``` -```js usePointerPosition.js +```js src/usePointerPosition.js import { useState, useEffect } from 'react'; export function usePointerPosition() { @@ -814,7 +814,7 @@ export function usePointerPosition() { } ``` -```js useDelayedValue.js +```js src/useDelayedValue.js import { useState, useEffect } from 'react'; export function useDelayedValue(value, delay) { diff --git a/src/content/learn/extracting-state-logic-into-a-reducer.md b/src/content/learn/extracting-state-logic-into-a-reducer.md index 67825d678..767e6f1a5 100644 --- a/src/content/learn/extracting-state-logic-into-a-reducer.md +++ b/src/content/learn/extracting-state-logic-into-a-reducer.md @@ -23,7 +23,7 @@ Plus vos composants deviennent complexes, plus il est difficile de voir d'un cou -```js App.js +```js src/App.js import { useState } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -79,7 +79,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -103,7 +103,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -398,7 +398,7 @@ Vous pourriez d'ailleurs utiliser la méthode `reduce()` avec un `initialState` -```js index.js active +```js src/index.js active import tasksReducer from './tasksReducer.js'; let initialState = []; @@ -415,7 +415,7 @@ const output = document.getElementById('output'); output.textContent = JSON.stringify(finalState, null, 2); ``` -```js tasksReducer.js +```js src/tasksReducer.js export default function tasksReducer(tasks, action) { switch (action.type) { case 'added': { @@ -493,7 +493,7 @@ Tout est câblé maintenant ! Ici, le réducteur est déclaré à la fin du fic -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -574,7 +574,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -598,7 +598,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -678,7 +678,7 @@ Si vous voulez, vous pouvez même déplacer le réducteur dans un fichier à par -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -730,7 +730,7 @@ const initialTasks = [ ]; ``` -```js tasksReducer.js +```js src/tasksReducer.js export default function tasksReducer(tasks, action) { switch (action.type) { case 'added': { @@ -762,7 +762,7 @@ export default function tasksReducer(tasks, action) { } ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -786,7 +786,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -889,7 +889,7 @@ Comme pour la [mise à jour des objets](/learn/updating-objects-in-state#write- -```js App.js +```js src/App.js import { useImmerReducer } from 'use-immer'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -964,7 +964,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({onAddTask}) { @@ -988,7 +988,7 @@ export default function AddTask({onAddTask}) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({tasks, onChangeTask, onDeleteTask}) { @@ -1126,7 +1126,7 @@ case 'changed_selection': { -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1160,7 +1160,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1188,7 +1188,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1209,7 +1209,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1276,7 +1276,7 @@ Voici l'exemple mis à jour afin pour envoyer les messages correspondants : -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1310,7 +1310,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1338,7 +1338,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1362,7 +1362,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1420,7 +1420,7 @@ Pour le moment, appuyer sur le bouton « Envoyer » ne fait rien du tout. Ajou -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1454,7 +1454,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1482,7 +1482,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1506,7 +1506,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1559,7 +1559,7 @@ Il existe plusieurs façons de procéder dans le gestionnaire d'événement du b -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1593,7 +1593,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1621,7 +1621,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1645,7 +1645,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1707,7 +1707,7 @@ Cependant, _du point de vue de l'utilisateur_, envoyer un message constitue une -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1741,7 +1741,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js active +```js src/messengerReducer.js active export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1775,7 +1775,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1799,7 +1799,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js active +```js src/Chat.js active import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -1856,7 +1856,7 @@ textarea { Le comportement visible reste identique. Cependant, gardez à l'esprit que les types d'action doivent idéalement décrire « ce qu'a fait l'utilisateur » plutôt que « la façon dont vous voulez que l'état change ». Respecter cette philosophie facilite l'ajout de fonctionnalités par la suite. -Quelle que soit l'approche retenue, il est important que vous ne placiez _pas_ l'`alert` dans un réducteur. Le réducteur doit être une fonction pure : il doit se limiter au calcul du prochain état. Il ne doit rien « faire », y compris afficher des messages à l'utilisateur. Ça doit être fait dans le gestionnaire d'événement (pour détecter ce genre d'erreur, React en mode strict appellera vos réducteurs plusieurs fois. Du coup, si vous placez une alerte dans un réducteur, vous la verrez deux fois). +Quelle que soit l'approche retenue, il est important que vous ne placiez _pas_ l'`alert` dans un réducteur. Le réducteur doit être une fonction pure : il doit se limiter au calcul du prochain état. Il ne doit rien « faire », y compris afficher des messages à l'utilisateur. Ça doit être fait dans le gestionnaire d'événement (pour détecter ce genre d'erreur, React en Mode Strict appellera vos réducteurs plusieurs fois. Du coup, si vous placez une alerte dans un réducteur, vous la verrez deux fois). @@ -1904,7 +1904,7 @@ La syntaxe `[key]: value` des [noms de propriétés calculés](https://developer -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -1938,7 +1938,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, message: 'Bonjour', @@ -1972,7 +1972,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -1996,7 +1996,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2079,7 +2079,7 @@ const message = state.messages[state.selectedId]; -```js App.js +```js src/App.js import { useReducer } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2113,7 +2113,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2156,7 +2156,7 @@ export function messengerReducer(state, action) { } ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2180,7 +2180,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2267,7 +2267,7 @@ Souvenez-vous qu'une fonction de réduction prend deux arguments — l'état co -```js App.js +```js src/App.js import { useReducer } from './MyReact.js'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2301,7 +2301,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2344,7 +2344,7 @@ export function messengerReducer(state, action) { } ``` -```js MyReact.js active +```js src/MyReact.js active import { useState } from 'react'; export function useReducer(reducer, initialState) { @@ -2356,7 +2356,7 @@ export function useReducer(reducer, initialState) { } ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2380,7 +2380,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js hidden +```js src/Chat.js hidden import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { @@ -2441,7 +2441,7 @@ textarea { -```js App.js +```js src/App.js import { useReducer } from './MyReact.js'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -2475,7 +2475,7 @@ const contacts = [ ]; ``` -```js messengerReducer.js +```js src/messengerReducer.js export const initialState = { selectedId: 0, messages: { @@ -2518,7 +2518,7 @@ export function messengerReducer(state, action) { } ``` -```js MyReact.js active +```js src/MyReact.js active import { useState } from 'react'; export function useReducer(reducer, initialState) { @@ -2533,7 +2533,7 @@ export function useReducer(reducer, initialState) { } ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({contacts, selectedId, dispatch}) { return (
@@ -2557,7 +2557,7 @@ export default function ContactList({contacts, selectedId, dispatch}) { } ``` -```js Chat.js hidden +```js src/Chat.js hidden import { useState } from 'react'; export default function Chat({contact, message, dispatch}) { diff --git a/src/content/learn/importing-and-exporting-components.md b/src/content/learn/importing-and-exporting-components.md index 1c67ece11..11be8c9d0 100644 --- a/src/content/learn/importing-and-exporting-components.md +++ b/src/content/learn/importing-and-exporting-components.md @@ -66,7 +66,7 @@ Et si vous souhaitiez changer l’écran d’accueil à l’avenir et y mettre u -```js App.js +```js src/App.js import Gallery from './Gallery.js'; export default function App() { @@ -76,7 +76,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Gallery.js'; @@ -193,7 +193,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js export function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Gallery.js'; @@ -280,7 +280,7 @@ export default function App() { } ``` -```js Gallery.js active +```js src/Gallery.js active // Déplace-moi vers Profile.js ! export function Profile() { return ( @@ -303,7 +303,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js ``` ```css @@ -320,7 +320,7 @@ Voici la solution avec les exports nommés : -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import { Profile } from './Profile.js'; @@ -334,7 +334,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js import { Profile } from './Profile.js'; export default function Gallery() { @@ -349,7 +349,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export function Profile() { return ( -```js App.js +```js src/App.js import Gallery from './Gallery.js'; import Profile from './Profile.js'; @@ -384,7 +384,7 @@ export default function App() { } ``` -```js Gallery.js +```js src/Gallery.js import Profile from './Profile.js'; export default function Gallery() { @@ -399,7 +399,7 @@ export default function Gallery() { } ``` -```js Profile.js +```js src/Profile.js export default function Profile() { return ( `. Par ailleurs, votre composant ne peut pas renvoyer plusieurs balises JSX. Il vous faudrait les enrober dans un parent commun, tel qu’un `
...
` ou un fragment `<>...` vide : +JSX est plus exigeant que HTML. Vous devez fermer les balises telles que `
`. Par ailleurs, votre composant ne peut pas renvoyer plusieurs balises JSX. Il vous faudrait les enrober dans un parent commun, tel qu’un `
...
` ou un Fragment `<>...` vide : ```js {3,6} function AboutPage() { diff --git a/src/content/learn/javascript-in-jsx-with-curly-braces.md b/src/content/learn/javascript-in-jsx-with-curly-braces.md index 26769c1e0..a7523e061 100644 --- a/src/content/learn/javascript-in-jsx-with-curly-braces.md +++ b/src/content/learn/javascript-in-jsx-with-curly-braces.md @@ -533,7 +533,7 @@ Vous pouvez aussi déplacer cette expression dans une fonction séparée genre ` -```js App.js +```js src/App.js import { getImageUrl } from './utils.js' const person = { @@ -565,7 +565,7 @@ export default function TodoList() { } ``` -```js utils.js +```js src/utils.js export function getImageUrl(person) { return ( 'https://i.imgur.com/' + diff --git a/src/content/learn/keeping-components-pure.md b/src/content/learn/keeping-components-pure.md index 116cc1d5b..229c82e35 100644 --- a/src/content/learn/keeping-components-pure.md +++ b/src/content/learn/keeping-components-pure.md @@ -12,7 +12,7 @@ Certaines fonctions JavaScript sont *pures*. Les fonctions pures se contentent d - Ce qu'est la pureté d'une fonction, et en quoi elle vous aide à éviter les bugs - Comment garder vos composants purs en ne modifiant rien pendant la phase de rendu -- Comment utiliser le mode strict pour détecter les erreurs dans vos composants +- Comment utiliser le Mode Strict pour détecter les erreurs dans vos composants @@ -49,7 +49,7 @@ React est fondé sur cette notion. **React suppose que chaque composant que vous -```js App.js +```js src/App.js function Recipe({ drinkers }) { return (
    @@ -153,11 +153,11 @@ Même si vous ne les avez pas encore toutes utilisées à ce stade, sachez que d Lorsque vous souhaitez *modifier* quelque chose en réaction à une interaction utilisateur, vous devriez [mettre à jour l'état](/learn/state-a-components-memory) plutôt que d'écrire dans une variable. Vous ne devriez jamais modifier des variables ou objets pré-existants lors du rendu de votre composant. -React propose un « mode strict » dans lequel il appelle chaque fonction composant deux fois pendant le développement. **En appelant chaque fonction composant deux fois, le mode strict vous aide à repérer les composants qui enfreignent ces règles.** +React propose un « Mode Strict » dans lequel il appelle chaque fonction composant deux fois pendant le développement. **En appelant chaque fonction composant deux fois, le Mode Strict vous aide à repérer les composants qui enfreignent ces règles.** Avez-vous remarqué que le premier exemple affichait « invité #2 », « invité #4 » et « invité #6 » au lieu de « invité #1 », « invité #2 » et « invité #3 » ? La fonction d'origine était impure, de sorte que l'appeler deux fois cassait son fonctionnement. Mais la fonction corrigée, qui est pure, fonctionne même si elle est systématiquement appelée deux fois. **Les fonctions pures font juste un calcul, aussi les appeler deux fois ne change rien**, tout comme appeler `double(2)` deux fois ne change pas son résultat, et résoudre y = 2x deux fois ne change pas la valeur de y. Mêmes entrées, même sorties. Toujours. -Le mode strict n'a aucun effet en production, il ne ralentira donc pas votre appli pour vos utilisateurs. Pour activer le mode strict, enrobez votre composant racine dans un ``. Certains frameworks mettent ça en place par défaut. +Le Mode Strict n'a aucun effet en production, il ne ralentira donc pas votre appli pour vos utilisateurs. Pour activer le Mode Strict, enrobez votre composant racine dans un ``. Certains frameworks mettent ça en place par défaut. @@ -241,7 +241,7 @@ Le rendu est un *calcul*, il ne devrait pas essayer de « faire » des choses. -```js Clock.js active +```js src/Clock.js active export default function Clock({ time }) { let hours = time.getHours(); if (hours >= 0 && hours <= 6) { @@ -257,7 +257,7 @@ export default function Clock({ time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -303,7 +303,7 @@ Vous pouvez corriger ce composant en calculant le `className` puis en l'incluant -```js Clock.js active +```js src/Clock.js active export default function Clock({ time }) { let hours = time.getHours(); let className; @@ -320,7 +320,7 @@ export default function Clock({ time }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import Clock from './Clock.js'; @@ -378,7 +378,7 @@ Le code problématique est dans `Profile.js`. Assurez-vous de bien l'avoir comp -```js Profile.js +```js src/Profile.js import Panel from './Panel.js'; import { getImageUrl } from './utils.js'; @@ -411,7 +411,7 @@ function Avatar() { } ``` -```js Panel.js hidden +```js src/Panel.js hidden import { useState } from 'react'; export default function Panel({ children }) { @@ -427,7 +427,7 @@ export default function Panel({ children }) { } ``` -```js App.js +```js src/App.js import Profile from './Profile.js'; export default function App() { @@ -446,7 +446,7 @@ export default function App() { } ``` -```js utils.js hidden +```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( 'https://i.imgur.com/' + @@ -479,7 +479,7 @@ Pour corriger ce bug, supprimez la variable `currentPerson`. Passez plutôt tou -```js Profile.js active +```js src/Profile.js active import Panel from './Panel.js'; import { getImageUrl } from './utils.js'; @@ -509,7 +509,7 @@ function Avatar({ person }) { } ``` -```js Panel.js hidden +```js src/Panel.js hidden import { useState } from 'react'; export default function Panel({ children }) { @@ -525,7 +525,7 @@ export default function Panel({ children }) { } ``` -```js App.js +```js src/App.js import Profile from './Profile.js'; export default function App() { @@ -544,7 +544,7 @@ export default function App() { } ``` -```js utils.js hidden +```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( 'https://i.imgur.com/' + @@ -581,7 +581,7 @@ Vous avez implémenté ce dernier en ajoutant une pseudo-histoire supplémentair -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { stories.push({ id: 'create', @@ -600,7 +600,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; @@ -674,7 +674,7 @@ li { -Remarquez que chaque fois que l'horloge change, « Créer une histoire » est ajoutée *deux fois*. C'est un indice que la mutation est dans notre rendu : le mode strict appelle les composants deux fois pour rendre ce type de soucis plus facile à remarquer. +Remarquez que chaque fois que l'horloge change, « Créer une histoire » est ajoutée *deux fois*. C'est un indice que la mutation est dans notre rendu : le Mode Strict appelle les composants deux fois pour rendre ce type de soucis plus facile à remarquer. La fonction `StoryTray` n'est pas pure. En appelant `push` sur le tableau `stories` reçu (une prop !), elle modifie un objet créé *avant* que `StoryTray` ait commencé son rendu. Ça donne un bug et un comportement imprévisible. @@ -682,7 +682,7 @@ Le correctif le plus simple consiste à ne pas toucher au tableau du tout, et à -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { return (
      @@ -697,7 +697,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; @@ -767,7 +767,7 @@ Une autre approche consisterait à créer un *nouveau* tableau (en partant de ce -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { // Copier le tableau ! let storiesToDisplay = stories.slice(); @@ -790,7 +790,7 @@ export default function StoryTray({ stories }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState, useEffect } from 'react'; import StoryTray from './StoryTray.js'; diff --git a/src/content/learn/lifecycle-of-reactive-effects.md b/src/content/learn/lifecycle-of-reactive-effects.md index ad74fd80e..43b61ee74 100644 --- a/src/content/learn/lifecycle-of-reactive-effects.md +++ b/src/content/learn/lifecycle-of-reactive-effects.md @@ -252,7 +252,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -448,7 +448,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -528,7 +528,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -647,7 +647,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -838,7 +838,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -913,7 +913,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1330,7 +1330,7 @@ Une mise en sourdine du *linter* est toujours suspecte. Serait-ce un bug ? -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; import { @@ -1375,7 +1375,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; export default function ChatRoom({ roomId, createConnection }) { @@ -1390,7 +1390,7 @@ export default function ChatRoom({ roomId, createConnection }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1428,7 +1428,7 @@ Si vous réactivez le *linter*, il vous indiquera une erreur. Le problème est q -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; import { @@ -1473,7 +1473,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; export default function ChatRoom({ roomId, createConnection }) { @@ -1487,7 +1487,7 @@ export default function ChatRoom({ roomId, createConnection }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1523,7 +1523,7 @@ Il est vrai que `createConnection` est une dépendance. Toutefois, ce code est u -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1561,7 +1561,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; import { createEncryptedConnection, @@ -1582,7 +1582,7 @@ export default function ChatRoom({ roomId, isEncrypted }) { } ``` -```js chat.js +```js src/chat.js export function createEncryptedConnection(roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1634,7 +1634,7 @@ Si vous avez deux processus de synchronisation différents, vous devez écrire d -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -1688,7 +1688,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); @@ -1783,7 +1783,7 @@ C'est pourquoi il est logique de les décrire comme deux Effets distincts. Voici -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -1856,7 +1856,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); @@ -1946,7 +1946,7 @@ Pour limiter la répétition, vous pouvez plutôt extraire une partie de la logi -```js App.js +```js src/App.js import { useState } from 'react'; import { useSelectOptions } from './useSelectOptions.js'; @@ -1992,7 +1992,7 @@ export default function Page() { } ``` -```js useSelectOptions.js +```js src/useSelectOptions.js import { useState, useEffect } from 'react'; import { fetchData } from './api.js'; @@ -2019,7 +2019,7 @@ export function useSelectOptions(url) { } ``` -```js api.js hidden +```js src/api.js hidden export function fetchData(url) { if (url === '/planets') { return fetchPlanets(); diff --git a/src/content/learn/managing-state.md b/src/content/learn/managing-state.md index ad033c086..0712ef6a5 100644 --- a/src/content/learn/managing-state.md +++ b/src/content/learn/managing-state.md @@ -310,7 +310,7 @@ Cependant, il arrive que ce ne soit pas ce que vous souhaitez. Dans cette appli -```js App.js +```js src/App.js import { useState } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -336,7 +336,7 @@ const contacts = [ ]; ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({ selectedContact, contacts, @@ -360,7 +360,7 @@ export default function ContactList({ } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({ contact }) { @@ -405,7 +405,7 @@ React vous permet d’outrepasser le comportement par défaut, et de *forcer* un -```js App.js +```js src/App.js import { useState } from 'react'; import Chat from './Chat.js'; import ContactList from './ContactList.js'; @@ -431,7 +431,7 @@ const contacts = [ ]; ``` -```js ContactList.js +```js src/ContactList.js export default function ContactList({ selectedContact, contacts, @@ -455,7 +455,7 @@ export default function ContactList({ } ``` -```js Chat.js +```js src/Chat.js import { useState } from 'react'; export default function Chat({ contact }) { @@ -508,7 +508,7 @@ Les composants comportant de nombreuses mises à jour d'état réparties entre d -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -591,7 +591,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -612,7 +612,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -736,7 +736,7 @@ export default function Page() { } ``` -```js Section.js +```js src/Section.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -752,7 +752,7 @@ export default function Section({ children }) { } ``` -```js Heading.js +```js src/Heading.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -779,7 +779,7 @@ export default function Heading({ children }) { } ``` -```js LevelContext.js +```js src/LevelContext.js import { createContext } from 'react'; export const LevelContext = createContext(0); @@ -810,7 +810,7 @@ Avec cette approche, un composant parent ayant un état complexe le gère à l -```js App.js +```js src/App.js import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; import { TasksProvider } from './TasksContext.js'; @@ -826,7 +826,7 @@ export default function TaskApp() { } ``` -```js TasksContext.js +```js src/TasksContext.js import { createContext, useContext, useReducer } from 'react'; const TasksContext = createContext(null); @@ -891,7 +891,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js +```js src/AddTask.js import { useState, useContext } from 'react'; import { useTasksDispatch } from './TasksContext.js'; @@ -920,7 +920,7 @@ export default function AddTask({ onAddTask }) { let nextId = 3; ``` -```js TaskList.js +```js src/TaskList.js import { useState, useContext } from 'react'; import { useTasks, useTasksDispatch } from './TasksContext.js'; diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 622beb6bf..859c203d7 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -1097,7 +1097,7 @@ Vous aurez besoin de `forwardRef` pour choisir d'exposer un nœud DOM pour votre -```js App.js +```js src/App.js import SearchButton from './SearchButton.js'; import SearchInput from './SearchInput.js'; @@ -1113,7 +1113,7 @@ export default function Page() { } ``` -```js SearchButton.js +```js src/SearchButton.js export default function SearchButton() { return ( ; } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -364,7 +364,7 @@ export default function Square() { -/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment `<>...`? +/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX Fragment `<>...`? @@ -459,7 +459,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -631,7 +631,7 @@ Votre code à jour devrait ressembler à ceci : -```js App.js +```js src/App.js function Square({ value }) { return ; } @@ -659,7 +659,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -813,7 +813,7 @@ Après que vous aurez fait les modifications ci-dessus, votre code devrait resse -```js App.js +```js src/App.js import { useState } from 'react'; function Square() { @@ -856,7 +856,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -994,7 +994,7 @@ Et votre code devrait ressembler à ceci : -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value }) { @@ -1025,7 +1025,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1236,7 +1236,7 @@ Voici à quoi votre code devrait ressembler : -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -1278,7 +1278,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1430,7 +1430,7 @@ Désormais, vous ne pouvez plus ajouter des `X` ou des `O` que sur les cases vid -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -1481,7 +1481,7 @@ export default function Board() { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1532,7 +1532,7 @@ body { Maintenant que les joueurs peuvent participer tour à tour, vous allez vouloir déterminer à quel moment la partie est gagnée, ou s'il n'y a plus de tour à jouer. Pour cela, ajoutez une petite fonction utilitaire nommée `calculateWinner` qui prend un tableau des 9 cases, vérifie s'il y a victoire et renvoie `'X'`, `'O'` ou `null` selon le cas. Ne vous préocuppez pas trop du code de `calculateWinner`, il n'a rien de spécifique à React : -```js App.js +```js src/App.js export default function Board() { //... } @@ -1602,7 +1602,7 @@ Félicitations ! Vous avez désormais un jeu fonctionnel de tic-tac-toe. Et vou -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -1682,7 +1682,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -1880,7 +1880,7 @@ Par exemple, si `history` vaut `[[null,null,null], ["X",null,null]]` et `nextSqu -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -1978,7 +1978,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2095,7 +2095,7 @@ Vous la corrigerez dans la prochaine section. -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2211,7 +2211,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2323,7 +2323,7 @@ const moves = history.map((squares, move) => { -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2440,7 +2440,7 @@ function calculateWinner(squares) { ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2544,7 +2544,7 @@ Si vous cliquez sur n'importe quelle étape de l'historique de la partie, le pla -```js App.js +```js src/App.js import { useState } from 'react'; function Square({value, onSquareClick}) { @@ -2664,7 +2664,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } @@ -2754,7 +2754,7 @@ Le résultat final est ici : -```js App.js +```js src/App.js import { useState } from 'react'; function Square({ value, onSquareClick }) { @@ -2872,7 +2872,7 @@ function calculateWinner(squares) { } ``` -```css styles.css +```css src/styles.css * { box-sizing: border-box; } diff --git a/src/content/learn/typescript.md b/src/content/learn/typescript.md index 3901d0aac..1d806b08b 100644 --- a/src/content/learn/typescript.md +++ b/src/content/learn/typescript.md @@ -54,7 +54,7 @@ Si on reprend le [composant `MyButton`](/learn#components) du guide de [démarra -```tsx App.tsx active +```tsx src/App.tsx active function MyButton({ title }: { title: string }) { return ( @@ -71,7 +71,7 @@ export default function MyApp() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -87,7 +87,7 @@ Cette syntaxe en ligne est la façon la plus rapide de fournir des types pour un -```tsx App.tsx active +```tsx src/App.tsx active interface MyButtonProps { /** Le texte à afficher dans le bouton */ title: string; @@ -111,7 +111,7 @@ export default function MyApp() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -169,7 +169,7 @@ Le [Hook `useReducer`](/reference/react/useReducer) est un Hook plus complexe qu -```tsx App.tsx active +```tsx src/App.tsx active import {useReducer} from 'react'; interface State { @@ -212,7 +212,7 @@ export default function App() { ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -246,7 +246,7 @@ Le type de la valeur fournie par le contexte est inféré à partir de la valeur -```tsx App.tsx active +```tsx src/App.tsx active import { createContext, useContext, useState } from 'react'; type Theme = "light" | "dark" | "system"; @@ -275,7 +275,7 @@ function MyComponent() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` @@ -379,7 +379,7 @@ Lorsque vous travaillez avec des événements DOM en React, le type de l'événe -```tsx App.tsx active +```tsx src/App.tsx active import { useState } from 'react'; export default function Form() { @@ -398,7 +398,7 @@ export default function Form() { } ``` -```js App.js hidden +```js src/App.js hidden import AppTSX from "./App.tsx"; export default App = AppTSX; ``` diff --git a/src/content/learn/understanding-your-ui-as-a-tree.md b/src/content/learn/understanding-your-ui-as-a-tree.md index e3991dd62..974236d32 100644 --- a/src/content/learn/understanding-your-ui-as-a-tree.md +++ b/src/content/learn/understanding-your-ui-as-a-tree.md @@ -39,7 +39,7 @@ Voici une appli React qui affiche des citations inspirantes. -```js App.js +```js src/App.js import FancyText from './FancyText'; import InspirationGenerator from './InspirationGenerator'; import Copyright from './Copyright'; @@ -57,7 +57,7 @@ export default function App() { ``` -```js FancyText.js +```js src/FancyText.js export default function FancyText({title, text}) { return title ?

      {text}

      @@ -65,7 +65,7 @@ export default function FancyText({title, text}) { } ``` -```js InspirationGenerator.js +```js src/InspirationGenerator.js import * as React from 'react'; import quotes from './quotes'; import FancyText from './FancyText'; @@ -86,13 +86,13 @@ export default function InspirationGenerator({children}) { } ``` -```js Copyright.js +```js src/Copyright.js export default function Copyright({year}) { return

      ©️ {year}

      ; } ``` -```js quotes.js +```js src/quotes.js export default [ "Ne laisse pas hier occuper trop d’aujourd’hui. — Will Rogers", "L’ambition, c’est poser une échelle contre le ciel.", @@ -148,7 +148,7 @@ Nous pouvons mettre à jour l'appli pour qu'elle affiche de façon conditionnell -```js App.js +```js src/App.js import FancyText from './FancyText'; import InspirationGenerator from './InspirationGenerator'; import Copyright from './Copyright'; @@ -166,7 +166,7 @@ export default function App() { ``` -```js FancyText.js +```js src/FancyText.js export default function FancyText({title, text}) { return title ?

      {text}

      @@ -174,13 +174,13 @@ export default function FancyText({title, text}) { } ``` -```js Color.js +```js src/Color.js export default function Color({value}) { return
      } ``` -```js InspirationGenerator.js +```js src/InspirationGenerator.js import * as React from 'react'; import inspirations from './inspirations'; import FancyText from './FancyText'; @@ -205,13 +205,13 @@ export default function InspirationGenerator({children}) { } ``` -```js Copyright.js +```js src/Copyright.js export default function Copyright({year}) { return

      ©️ {year}

      ; } ``` -```js inspirations.js +```js src/inspirations.js export default [ {type: 'quote', value: "Ne laisse pas hier occuper trop d’aujourd’hui. — Will Rogers"}, {type: 'color', value: "#B73636"}, diff --git a/src/content/learn/updating-arrays-in-state.md b/src/content/learn/updating-arrays-in-state.md index 1c62da3a1..633abb5ad 100644 --- a/src/content/learn/updating-arrays-in-state.md +++ b/src/content/learn/updating-arrays-in-state.md @@ -1084,7 +1084,7 @@ Dans cet exemple, tous les gestionnaires d'événements dans `App.js` utilisent -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -1139,7 +1139,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1160,7 +1160,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1247,7 +1247,7 @@ Dans `handleAddTodo`, vous pouvez utiliser la syntaxe de *spread* de tableaux. D -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -1306,7 +1306,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1327,7 +1327,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1417,7 +1417,7 @@ Il s'agit du même exemple que dans l'exercice précédent. Cette fois-ci, corri -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1473,7 +1473,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1494,7 +1494,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1599,7 +1599,7 @@ Avec Immer, vous pouvez écrire du code de manière modifiante, tant que vous ne -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1661,7 +1661,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1682,7 +1682,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1787,7 +1787,7 @@ Par exemple, dans cette version, `handleAddTodo` est implémenté en modifiant l -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import AddTodo from './AddTodo.js'; @@ -1846,7 +1846,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -1867,7 +1867,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ diff --git a/src/content/learn/updating-objects-in-state.md b/src/content/learn/updating-objects-in-state.md index fd66f0d5b..9f601052c 100644 --- a/src/content/learn/updating-objects-in-state.md +++ b/src/content/learn/updating-objects-in-state.md @@ -984,7 +984,7 @@ S’il y a un changement inattendu, il y a une mutation. Trouvez la mutation dan -```js App.js +```js src/App.js import { useState } from 'react'; import Background from './Background.js'; import Box from './Box.js'; @@ -1037,7 +1037,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1100,7 +1100,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1134,7 +1134,7 @@ La solution consiste à retirer la mutation de `handleMove` et à utiliser la sy -```js App.js +```js src/App.js import { useState } from 'react'; import Background from './Background.js'; import Box from './Box.js'; @@ -1192,7 +1192,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1255,7 +1255,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1289,7 +1289,7 @@ Il s’agit du même exemple défectueux que dans l’exercice précédent. Cett -```js App.js +```js src/App.js import { useState } from 'react'; import { useImmer } from 'use-immer'; import Background from './Background.js'; @@ -1343,7 +1343,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1406,7 +1406,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { @@ -1456,7 +1456,7 @@ Voici la solution réécrite avec Immer. Voyez comme les gestionnaires d’évé -```js App.js +```js src/App.js import { useImmer } from 'use-immer'; import Background from './Background.js'; import Box from './Box.js'; @@ -1510,7 +1510,7 @@ export default function Canvas() { } ``` -```js Box.js +```js src/Box.js import { useState } from 'react'; export default function Box({ @@ -1573,7 +1573,7 @@ export default function Box({ } ``` -```js Background.js +```js src/Background.js export default function Background({ position }) { diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ab7fa167d..64eed03e8 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -151,7 +151,7 @@ console.timeEnd('filtrage tableau'); Gardez à l’esprit que votre machine est probablement plus rapide que celles de vos utilisateurs, il est donc recommandé de tester la performance au sein d’un ralentissement artificiel. Par exemple, Chrome propose une option de [bridage processeur](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) exprès pour ça. -Remarquez aussi que mesurer la performance en développement ne vous donnera pas des résultats très précis. (Par exemple, quand le [mode strict](/reference/react/StrictMode) est actif, chaque composant fait deux rendus au lieu d’un.) Pour améliorer la pertinence de vos mesures, construisez la version de production de votre appli et testez-la sur des appareils similaires à ceux de vos utilisateurs. +Remarquez aussi que mesurer la performance en développement ne vous donnera pas des résultats très précis. (Par exemple, quand le [Mode Strict](/reference/react/StrictMode) est actif, chaque composant fait deux rendus au lieu d’un.) Pour améliorer la pertinence de vos mesures, construisez la version de production de votre appli et testez-la sur des appareils similaires à ceux de vos utilisateurs. @@ -883,7 +883,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; export function createTodo(text, completed = false) { @@ -976,7 +976,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; export function createTodo(text, completed = false) { @@ -1062,7 +1062,7 @@ export default function TodoList() { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1145,7 +1145,7 @@ export default function TodoList() { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1234,7 +1234,7 @@ function NewTodo({ onAdd }) { } ``` -```js todos.js +```js src/todos.js let nextId = 0; let calls = 0; @@ -1279,7 +1279,7 @@ Lorsque vous sélectionnez un contact au moyen des boutons du haut, le formulair -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ContactList from './ContactList.js'; import EditContact from './EditContact.js'; @@ -1331,7 +1331,7 @@ const initialContacts = [ ]; ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({ contacts, selectedId, @@ -1358,7 +1358,7 @@ export default function ContactList({ } ``` -```js EditContact.js active +```js src/EditContact.js active import { useState, useEffect } from 'react'; export default function EditContact({ savedContact, onSave }) { @@ -1443,7 +1443,7 @@ Découpez le composant `EditContact` en deux. Déplacez tout l’état du formu -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ContactList from './ContactList.js'; import EditContact from './EditContact.js'; @@ -1495,7 +1495,7 @@ const initialContacts = [ ]; ``` -```js ContactList.js hidden +```js src/ContactList.js hidden export default function ContactList({ contacts, selectedId, @@ -1522,7 +1522,7 @@ export default function ContactList({ } ``` -```js EditContact.js active +```js src/EditContact.js active import { useState } from 'react'; export default function EditContact(props) { diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 9428c9226..a1871ca66 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -151,7 +151,7 @@ En général, vous n'aurez besoin de ce code qu'une fois, au démarrage. Il va  ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; @@ -160,7 +160,7 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -230,7 +230,7 @@ Dans l'exemple ci-dessous, deux composants React distincts sont affichés dans d ``` -```js index.js active +```js src/index.js active import './styles.css'; import { createRoot } from 'react-dom/client'; import { Comments, Navigation } from './Components.js'; @@ -244,7 +244,7 @@ const commentRoot = createRoot(commentDomNode); commentRoot.render(); ``` -```js Components.js +```js src/Components.js export function Navigation() { return (
        @@ -311,7 +311,7 @@ Vous pouvez appeler `render` plus d'une fois sur la même racine. Tant que la st -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; @@ -325,7 +325,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 55abc331d..25735a431 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -140,7 +140,7 @@ Pour hydrater votre appli, React « attachera » la logique de vos composants

        Salut tout le monde !

        ``` -```js index.js active +```js src/index.js active import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -151,7 +151,7 @@ hydrateRoot( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -245,7 +245,7 @@ Pour éviter les avertissements d'hydratation sur un élément spécifique, ajou

        Date actuelle : 01/01/2020

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -253,7 +253,7 @@ import App from './App.js'; hydrateRoot(document.getElementById('root'), ); ``` -```js App.js active +```js src/App.js active export default function App() { return (

        @@ -283,7 +283,7 @@ Si vous différenciez volontairement l'affichage entre le côté serveur et le c

        Côté serveur

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; @@ -291,7 +291,7 @@ import App from './App.js'; hydrateRoot(document.getElementById('root'), ); ``` -```js App.js active +```js src/App.js active import { useState, useEffect } from "react"; export default function App() { @@ -337,7 +337,7 @@ Si vous appelez `root.render` après l'hydratation, et que la structure de l'arb

        Salut tout le monde ! 0

        ``` -```js index.js active +```js src/index.js active import { hydrateRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; @@ -354,7 +354,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md index 2f8e4f733..2cc23178b 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -769,7 +769,7 @@ Dans l'exemple ci-dessus, `style={{}}` n'est pas une syntaxe particulière, mais -```js App.js +```js src/App.js import Avatar from './Avatar.js'; const user = { @@ -783,7 +783,7 @@ export default function App() { } ``` -```js Avatar.js active +```js src/Avatar.js active export default function Avatar({ user }) { return ( +L'objet `{__html}` est censé être produit le plus près possible de la génération effective du HTML, comme le fait l'exemple précédent dans la fonction `renderMarkdownToHTML`. Ça garantit que tous les morceaux de HTML brut dans votre code sont explicitement identifiés comme tels, et que seules les variables dans le contenu desquelles vous anticipez la présence de HTML sont passées à `dangerouslySetInnerHTML`. Nous vous déconseillons de créer ces objets à la volée comme dans `
        `. + Pour comprendre pourquoi l'injection d'un contenu HTML quelconque est dangereuse, remplacez le code plus haut par celui-ci : ```js {1-4,7,8} diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 3721ba320..9031bf56e 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -61,7 +61,7 @@ Passez une fonction à la prop `action` du formulaire pour exécuter cette fonct -```js App.js +```js src/App.js export default function Search() { function search(formData) { const query = formData.get("query"); @@ -146,7 +146,7 @@ Nous utilisons ci-dessous la propriété `pending` pour indiquer que le formulai -```js App.js +```js src/App.js import { useFormStatus } from "react-dom"; import { submitForm } from "./actions.js"; @@ -172,7 +172,7 @@ export default function App() { } ``` -```js actions.js hidden +```js src/actions.js hidden export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } @@ -201,7 +201,7 @@ Lorsqu'un utilisateur saisit par exemple un message dans un formulaire puis cliq -```js App.js +```js src/App.js import { useOptimistic, useState, useRef } from "react"; import { deliverMessage } from "./actions.js"; @@ -251,7 +251,7 @@ export default function App() { } ``` -```js actions.js +```js src/actions.js export async function deliverMessage(message) { await new Promise((res) => setTimeout(res, 1000)); return message; @@ -281,7 +281,7 @@ Il peut arriver que la fonction appelée par la prop `action` de `` lève -```js App.js +```js src/App.js import { ErrorBoundary } from "react-error-boundary"; export default function Search() { @@ -332,7 +332,7 @@ Afin d'afficher un message d'erreur d'envoi de formulaire avant même que le *bu -```js App.js +```js src/App.js import { useFormState } from "react-dom"; import { signUpNewUser } from "./api"; @@ -363,7 +363,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden let emails = []; export async function signUpNewUser(newEmail) { @@ -398,7 +398,7 @@ Lorsque l'utilisateur active un bouton précis, le formulaire est envoyé, et l' -```js App.js +```js src/App.js export default function Search() { function publish(formData) { const content = formData.get("content"); diff --git a/src/content/reference/react-dom/components/textarea.md b/src/content/reference/react-dom/components/textarea.md index 562273e4a..4fb62109a 100644 --- a/src/content/reference/react-dom/components/textarea.md +++ b/src/content/reference/react-dom/components/textarea.md @@ -297,7 +297,7 @@ export default function MarkdownEditor() { } ``` -```js MarkdownPreview.js +```js src/MarkdownPreview.js import { Remarkable } from 'remarkable'; const md = new Remarkable(); diff --git a/src/content/reference/react-dom/createPortal.md b/src/content/reference/react-dom/createPortal.md index a2f949261..e869a487f 100644 --- a/src/content/reference/react-dom/createPortal.md +++ b/src/content/reference/react-dom/createPortal.md @@ -136,7 +136,7 @@ Dans cet exemple, les deux conteneurs ont des styles qui perturbent la boîte de -```js App.js active +```js src/App.js active import NoPortalExample from './NoPortalExample'; import PortalExample from './PortalExample'; @@ -154,7 +154,7 @@ export default function App() { } ``` -```js NoPortalExample.js +```js src/NoPortalExample.js import { useState } from 'react'; import ModalContent from './ModalContent.js'; @@ -173,7 +173,7 @@ export default function NoPortalExample() { } ``` -```js PortalExample.js active +```js src/PortalExample.js active import { useState } from 'react'; import { createPortal } from 'react-dom'; import ModalContent from './ModalContent.js'; @@ -194,7 +194,7 @@ export default function PortalExample() { } ``` -```js ModalContent.js +```js src/ModalContent.js export default function ModalContent({ onClose }) { return (
        @@ -206,7 +206,7 @@ export default function ModalContent({ onClose }) { ``` -```css styles.css +```css src/styles.css .clipping-container { position: relative; border: 1px solid #aaa; @@ -268,7 +268,7 @@ Les portails peuvent vous être utiles si votre racine React n'est qu'une partie ``` -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.js'; @@ -282,7 +282,7 @@ root.render( ); ``` -```js App.js active +```js src/App.js active import { createPortal } from 'react-dom'; const sidebarContentEl = document.getElementById('sidebar-content'); @@ -397,7 +397,7 @@ Voici un exemple complet avec lequel vous pouvez jouer : } ``` -```js App.js +```js src/App.js import { useRef, useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import { createMapWidget, addPopupToMapWidget } from './map-widget.js'; @@ -427,7 +427,7 @@ export default function Map() { } ``` -```js map-widget.js +```js src/map-widget.js import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; diff --git a/src/content/reference/react-dom/findDOMNode.md b/src/content/reference/react-dom/findDOMNode.md index 8d8d3797c..0cfad5dbd 100644 --- a/src/content/reference/react-dom/findDOMNode.md +++ b/src/content/reference/react-dom/findDOMNode.md @@ -81,7 +81,7 @@ Ici, la variable `input` sera définie à l'élément DOM ``. Ça vous pe -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -99,7 +99,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; @@ -129,7 +129,7 @@ Un code qui utilise `findDOMNode` est fragile parce que la relation entre le nœ -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -147,7 +147,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; @@ -172,7 +172,7 @@ Dans cet exemple, `findDOMNode` n'est plus utilisé. On utilise plutôt `inputRe -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -190,7 +190,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { createRef, Component } from 'react'; class AutoselectingInput extends Component { @@ -217,7 +217,7 @@ Dans les versions modernes de React sans les composants à base de classes, le c -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -235,7 +235,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { useRef, useEffect } from 'react'; export default function AutoselectingInput() { @@ -262,7 +262,7 @@ Dans l'exemple qui suit, `findDOMNode(this)` trouve un nœud DOM qui appartient -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -280,7 +280,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { Component } from 'react'; import { findDOMNode } from 'react-dom'; import MyInput from './MyInput.js'; @@ -298,7 +298,7 @@ class AutoselectingInput extends Component { export default AutoselectingInput; ``` -```js MyInput.js +```js src/MyInput.js export default function MyInput() { return ; } @@ -317,7 +317,7 @@ C'est ce que fait cette version, qui n'a donc plus besoin de `findDOMNode` : -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -335,7 +335,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { createRef, Component } from 'react'; import MyInput from './MyInput.js'; @@ -357,7 +357,7 @@ class AutoselectingInput extends Component { export default AutoselectingInput; ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { @@ -373,7 +373,7 @@ Voici à quoi ressemblerait ce code avec des fonctions composants au lieu de cla -```js App.js +```js src/App.js import { useState } from 'react'; import AutoselectingInput from './AutoselectingInput.js'; @@ -391,7 +391,7 @@ export default function App() { } ``` -```js AutoselectingInput.js active +```js src/AutoselectingInput.js active import { useRef, useEffect } from 'react'; import MyInput from './MyInput.js'; @@ -407,7 +407,7 @@ export default function AutoselectingInput() { } ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index e1fbcedac..48d930b5d 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -82,7 +82,7 @@ Par exemple, l'API `onbeforeprint` du navigateur vous permet de modifier la page -```js App.js active +```js src/App.js active import { useState, useEffect } from 'react'; import { flushSync } from 'react-dom'; diff --git a/src/content/reference/react-dom/hooks/useFormState.md b/src/content/reference/react-dom/hooks/useFormState.md index 601bcd250..df5ec641f 100644 --- a/src/content/reference/react-dom/hooks/useFormState.md +++ b/src/content/reference/react-dom/hooks/useFormState.md @@ -121,7 +121,7 @@ Pour afficher des messages tels qu'un message d'erreur ou une notification renvo -```js App.js +```js src/App.js import { useState } from "react"; import { useFormState } from "react-dom"; import { addToCart } from "./actions.js"; @@ -148,7 +148,7 @@ export default function App() { } ``` -```js actions.js +```js src/actions.js "use server"; export async function addToCart(prevState, queryData) { @@ -161,7 +161,7 @@ export async function addToCart(prevState, queryData) { } ``` -```css styles.css hidden +```css src/styles.css hidden form { border: solid 1px black; margin-bottom: 24px; @@ -194,7 +194,7 @@ La valeur renvoyée par une Action Serveur peut être n'importe quelle valeur s -```js App.js +```js src/App.js import { useState } from "react"; import { useFormState } from "react-dom"; import { addToCart } from "./actions.js"; @@ -230,7 +230,7 @@ export default function App() { } ``` -```js actions.js +```js src/actions.js "use server"; export async function addToCart(prevState, queryData) { @@ -249,7 +249,7 @@ export async function addToCart(prevState, queryData) { } ``` -```css styles.css hidden +```css src/styles.css hidden form { border: solid 1px black; margin-bottom: 24px; diff --git a/src/content/reference/react-dom/hooks/useFormStatus.md b/src/content/reference/react-dom/hooks/useFormStatus.md index 7ea9b97dd..e1ac9ce44 100644 --- a/src/content/reference/react-dom/hooks/useFormStatus.md +++ b/src/content/reference/react-dom/hooks/useFormStatus.md @@ -38,7 +38,7 @@ function Submit() { return } -export default App() { +export default function App() { return ( @@ -87,7 +87,7 @@ Nous utilisons ci-dessous la propriété `pending` pour indiquer que le formulai -```js App.js +```js src/App.js import { useFormStatus } from "react-dom"; import { submitForm } from "./actions.js"; @@ -113,7 +113,7 @@ export default function App() { } ``` -```js actions.js hidden +```js src/actions.js hidden export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } @@ -178,7 +178,7 @@ Dans l'exemple ci-dessous, nous avons un formulaire permettant à l'utilisateur -```js UsernameForm.js active +```js src/UsernameForm.js active import {useState, useMemo, useRef} from 'react'; import {useFormStatus} from 'react-dom'; @@ -219,7 +219,7 @@ export default function UsernameForm() { } ``` -```js App.js +```js src/App.js import UsernameForm from './UsernameForm'; import { submitForm } from "./actions.js"; @@ -232,7 +232,7 @@ export default function App() { } ``` -```js actions.js hidden +```js src/actions.js hidden export async function submitForm(query) { await new Promise((res) => setTimeout(res, 1000)); } diff --git a/src/content/reference/react-dom/hydrate.md b/src/content/reference/react-dom/hydrate.md index 897b8e0c1..961976985 100644 --- a/src/content/reference/react-dom/hydrate.md +++ b/src/content/reference/react-dom/hydrate.md @@ -89,7 +89,7 @@ Dans des applis entièrement construites avec React, **vous n'aurez généraleme

        Salut tout le monde !

        ``` -```js index.js active +```js src/index.js active import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -97,7 +97,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js +```js src/App.js export default function App() { return

        Salut tout le monde !

        ; } @@ -127,7 +127,7 @@ Pour éviter les avertissements d'hydratation sur un élément, ajoutez-lui `sup

        Nous sommes le 01/01/2020

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -135,7 +135,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js active +```js src/App.js active export default function App() { return (

        @@ -165,7 +165,7 @@ Si vous cherchez explicitement à produire un contenu différent sur le serveur

        Côté serveur

        ``` -```js index.js +```js src/index.js import './styles.css'; import { hydrate } from 'react-dom'; import App from './App.js'; @@ -173,7 +173,7 @@ import App from './App.js'; hydrate(, document.getElementById('root')); ``` -```js App.js active +```js src/App.js active import { useState, useEffect } from "react"; export default function App() { diff --git a/src/content/reference/react-dom/render.md b/src/content/reference/react-dom/render.md index 542bcfe64..5bd5e6e56 100644 --- a/src/content/reference/react-dom/render.md +++ b/src/content/reference/react-dom/render.md @@ -85,7 +85,7 @@ Dans les applis entièrement construites avec React, **vous voudrez généraleme -```js index.js active +```js src/index.js active import './styles.css'; import { render } from 'react-dom'; import App from './App.js'; @@ -93,7 +93,7 @@ import App from './App.js'; render(, document.getElementById('root')); ``` -```js App.js +```js src/App.js export default function App() { return

        Salut tout le monde !

        ; } @@ -119,7 +119,7 @@ Si votre page [n'est pas entièrement constuite avec React](/learn/add-react-to- ``` -```js index.js active +```js src/index.js active import './styles.css'; import { render } from 'react-dom'; import { Comments, Navigation } from './Components.js'; @@ -135,7 +135,7 @@ render( ); ``` -```js Components.js +```js src/Components.js export function Navigation() { return (
          @@ -187,7 +187,7 @@ Vous pouvez appeler `render` plusieurs fois sur le même nœud DOM. Tant que la -```js index.js active +```js src/index.js active import { render } from 'react-dom'; import './styles.css'; import App from './App.js'; @@ -202,7 +202,7 @@ setInterval(() => { }, 1000); ``` -```js App.js +```js src/App.js export default function App({counter}) { return ( <> diff --git a/src/content/reference/react-dom/server/renderToNodeStream.md b/src/content/reference/react-dom/server/renderToNodeStream.md index 005b623d9..64f786f8c 100644 --- a/src/content/reference/react-dom/server/renderToNodeStream.md +++ b/src/content/reference/react-dom/server/renderToNodeStream.md @@ -43,6 +43,9 @@ Côté client, appelez [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) * `reactNode` : un nœud React dont vous souhaitez produire le HTML. Ça pourrait par exemple être un élément JSX tel que ``. +* `options` **optionnelles** : un objet avec des options pour le rendu côté serveur. + * `identifierPrefix` **optionnel** : un préfixe textuel utilisé pour les ID générés par [`useId`](/reference/react/useId). Pratique pour éviter les conflits entre les ID au sein de racines multiples sur une même page. Doit être le même préfixe que celui passé à[`hydrateRoot`](/reference/react-dom/client/hydrateRoot#parameters). + #### Valeur renvoyée {/*returns*/} Un [flux Node.js en lecture](https://nodejs.org/api/stream.html#readable-streams) qui produit le texte HTML. diff --git a/src/content/reference/react-dom/server/renderToStaticMarkup.md b/src/content/reference/react-dom/server/renderToStaticMarkup.md index 7038b0a4c..21d29b3c0 100644 --- a/src/content/reference/react-dom/server/renderToStaticMarkup.md +++ b/src/content/reference/react-dom/server/renderToStaticMarkup.md @@ -35,6 +35,8 @@ Elle renverra le HTML non interactif de vos composants React. #### Paramètres {/*parameters*/} * `reactNode` : un nœud React dont vous voulez obtenir le HTML. Ça pourrait par exemple être un nœud JSX tel que ``. +* `options` **optionnelles** : un objet avec des options pour le rendu côté serveur. + * `identifierPrefix` **optionnel** : un préfixe textuel utilisé pour les ID générés par [`useId`](/reference/react/useId). Pratique pour éviter les conflits entre les ID au sein de racines multiples sur une même page. #### Valeur renvoyée {/*returns*/} diff --git a/src/content/reference/react-dom/server/renderToStaticNodeStream.md b/src/content/reference/react-dom/server/renderToStaticNodeStream.md index 270d60239..35ecbd9ce 100644 --- a/src/content/reference/react-dom/server/renderToStaticNodeStream.md +++ b/src/content/reference/react-dom/server/renderToStaticNodeStream.md @@ -36,6 +36,8 @@ Le flux émettra le HTML non interactif de vos composants React. #### Paramètres {/*parameters*/} * `reactNode` : un nœud React dont vous voulez obtenir le HTML. Ça pourrait par exemple être un nœud JSX tel que ``. +* `options` **optionnelles** : un objet avec des options pour le rendu côté serveur. + * `identifierPrefix` **optionnel** : un préfixe textuel utilisé pour les ID générés par [`useId`](/reference/react/useId). Pratique pour éviter les conflits entre les ID au sein de racines multiples sur une même page. #### Valeur renvoyée {/*returns*/} diff --git a/src/content/reference/react-dom/server/renderToString.md b/src/content/reference/react-dom/server/renderToString.md index d09daf7ab..eac0770ec 100644 --- a/src/content/reference/react-dom/server/renderToString.md +++ b/src/content/reference/react-dom/server/renderToString.md @@ -41,6 +41,8 @@ Côté client, appelez [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) #### Paramètres {/*parameters*/} * `reactNode` : un nœud React dont vous souhaitez produire le HTML. Ça pourrait par exemple être un élément JSX tel que ``. +* `options` **optionnelles** : un objet avec des options pour le rendu côté serveur. + * `identifierPrefix` **optionnel** : un préfixe textuel utilisé pour les ID générés par [`useId`](/reference/react/useId). Pratique pour éviter les conflits entre les ID au sein de racines multiples sur une même page. #### Valeur renvoyée {/*returns*/} diff --git a/src/content/reference/react-dom/unmountComponentAtNode.md b/src/content/reference/react-dom/unmountComponentAtNode.md index 94086100d..ef0a1c926 100644 --- a/src/content/reference/react-dom/unmountComponentAtNode.md +++ b/src/content/reference/react-dom/unmountComponentAtNode.md @@ -88,7 +88,7 @@ Dans l'exemple ci-dessous, cliquez sur « Afficher l'appli React » pour… aff ``` -```js index.js active +```js src/index.js active import './styles.css'; import { render, unmountComponentAtNode } from 'react-dom'; import App from './App.js'; @@ -104,7 +104,7 @@ document.getElementById('unmount').addEventListener('click', () => { }); ``` -```js App.js +```js src/App.js export default function App() { return

          Salut tout le monde !

          ; } diff --git a/src/content/reference/react/Children.md b/src/content/reference/react/Children.md index 984280ef7..f7e7b6dee 100644 --- a/src/content/reference/react/Children.md +++ b/src/content/reference/react/Children.md @@ -33,7 +33,7 @@ const mappedChildren = Children.map(children, child => Appelez `Children.count(children)` pour compter les enfants dans la structure de données `children`. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function RowList({ children }) { @@ -58,7 +58,7 @@ Le nombre de nœuds dans ces `children`. #### Limitations {/*children-count-caveats*/} -- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [fragments](/reference/react/Fragment) ne sont pas traversés non plus. +- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [Fragments](/reference/react/Fragment) ne sont pas traversés non plus. --- @@ -66,7 +66,7 @@ Le nombre de nœuds dans ces `children`. Appelez `Children.forEach(children, fn, thisArg?)` pour exécuter du code pour chaque enfant dans la structure de données `children`. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function SeparatorList({ children }) { @@ -92,7 +92,7 @@ function SeparatorList({ children }) { #### Limitations {/*children-foreach-caveats*/} -- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [fragments](/reference/react/Fragment) ne sont pas traversés non plus. +- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [Fragments](/reference/react/Fragment) ne sont pas traversés non plus. --- @@ -100,7 +100,7 @@ function SeparatorList({ children }) { Appelez `Children.map(children, fn, thisArg?)` pour produire une transformée de chaque enfant dans la structure de données `children`. -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; function RowList({ children }) { @@ -132,7 +132,7 @@ Dans le cas contraire, renvoie un tableau plat constitué des nœuds que vous av #### Limitations {/*children-map-caveats*/} -- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [fragments](/reference/react/Fragment) ne sont pas traversés non plus. +- Les nœuds vides (`null`, `undefined` et les booléens), les chaînes de caractères, les nombres, les [éléments React](/reference/react/createElement) sont tous comptabilisés. Les tableaux ne comptent pas comme des nœuds individuels, mais leurs enfants si. **La traversée s'arrête aux éléments React** : leur rendu n'est pas effectué, et leurs enfants ne sont pas traversés. Les [Fragments](/reference/react/Fragment) ne sont pas traversés non plus. - Si vous renvoyez un élément ou un tableau d'éléments avec des clés depuis `fn`, **les clés des éléments renvoyés seront automatiquement combinées avec la clé de l'élément correspondant dans `children`**. Lorsque vous renvoyez plusieurs éléments depuis `fn` sous forme d'un tableau, leurs clés n'ont besoin d'être uniques qu'entre elles. @@ -169,7 +169,7 @@ Dans le cas contraire, lève une erreur. Appelez `Children.toArray(children)` pour créer un tableau à partir de la structure de données `children`. -```js ReversedList.js active +```js src/ReversedList.js active import { Children } from 'react'; export default function ReversedList({ children }) { @@ -258,7 +258,7 @@ export default function App() { } ``` -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; export default function RowList({ children }) { @@ -336,7 +336,7 @@ function MoreRows() { } ``` -```js RowList.js +```js src/RowList.js import { Children } from 'react'; export default function RowList({ children }) { @@ -395,7 +395,7 @@ export default function App() { } ``` -```js SeparatorList.js active +```js src/SeparatorList.js active import { Children } from 'react'; export default function SeparatorList({ children }) { @@ -439,7 +439,7 @@ export default function App() { } ``` -```js RowList.js active +```js src/RowList.js active import { Children } from 'react'; export default function RowList({ children }) { @@ -510,7 +510,7 @@ export default function App() { } ``` -```js ReversedList.js active +```js src/ReversedList.js active import { Children } from 'react'; export default function ReversedList({ children }) { @@ -572,7 +572,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ children }) { return (
          @@ -639,7 +639,7 @@ function MoreRows() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ children }) { return (
          @@ -698,7 +698,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js export function RowList({ rows }) { return (
          @@ -761,7 +761,7 @@ export default function App() { } ``` -```js TabSwitcher.js +```js src/TabSwitcher.js import { useState } from 'react'; export default function TabSwitcher({ tabs }) { @@ -817,7 +817,7 @@ export default function App() { } ``` -```js TabSwitcher.js +```js src/TabSwitcher.js import { useState } from 'react'; export default function TabSwitcher({ tabIds, getHeader, renderContent }) { @@ -869,7 +869,7 @@ export default function App() { } ``` -```js RowList.js +```js src/RowList.js import { Fragment } from 'react'; export function RowList({ rowIds, renderRow }) { diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 7b844b14e..74a9572c2 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -204,7 +204,7 @@ Un constructeur ne devrait contenir aucun effet de bord ni aucun abonnement. * Lorsque vous faites du [rendu côté serveur](/reference/react-dom/server), le constructeur sera exécuté côté serveur aussi, suivi de la méthode [`render`](#render). En revanche, les méthodes de cycle de vie telles que `componentDidMount` ou `componentWillUnmount` ne seront pas exécutées côté serveur. -* En [mode strict](/reference/react/StrictMode), React appellera votre `constructor` deux fois en développement, puis jettera une des instances obtenues. Ce comportement vous permet de repérer des effets de bord involontaires qui doivent être sortis du `constructor`. +* En [Mode Strict](/reference/react/StrictMode), React appellera votre `constructor` deux fois en développement, puis jettera une des instances obtenues. Ce comportement vous permet de repérer des effets de bord involontaires qui doivent être sortis du `constructor`. @@ -292,7 +292,7 @@ class ChatRoom extends Component { #### Limitations {/*componentdidmount-caveats*/} -- En [mode strict](/reference/react/StrictMode), en développement React appellera `componentDidMount`, puis appellera immédiatement [`componentWillUnmount`](#componentwillunmount) et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique présente dans `componentDidMount`. +- En [Mode Strict](/reference/react/StrictMode), en développement React appellera `componentDidMount`, puis appellera immédiatement [`componentWillUnmount`](#componentwillunmount) et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique présente dans `componentDidMount`. - Même si vous pourriez appeler immédiatement [`setState`](#setstate) dans `componentDidMount`, il est préférable de l'éviter autant que possible. Ça déclencherait un rendu supplémentaire, qui arriverait toutefois avant que le navigateur n'ait mis à jour l'affichage. Ça garantit que même si la méthode [`render`](#render) est bien appelée deux fois dans un tel cas, l'utilisateur ne verra pas l'état intermédiaire. Utilisez cette approche avec précaution, parce qu'elle nuit aux performances. La plupart du temps, vous devriez pouvoir plutôt définir l'état initial dans le [`constructor`](#constructor). Ça reste toutefois utile pour des cas comme les boîtes de dialogue modales et les infobulles, qui nécessitent une mesure de nœud DOM avant de pouvoir afficher quelque chose qui dépend de leur taille ou de leur position. @@ -454,7 +454,7 @@ class ChatRoom extends Component { #### Limitations {/*componentwillunmount-caveats*/} -- En [mode strict](/reference/react/StrictMode), en développement React appellera `componentDidMount`, puis appellera immédiatement [`componentWillUnmount`](#componentwillunmount) et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique présente dans `componentDidMount`. +- En [Mode Strict](/reference/react/StrictMode), en développement React appellera `componentDidMount`, puis appellera immédiatement [`componentWillUnmount`](#componentwillunmount) et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique présente dans `componentDidMount`. @@ -608,7 +608,7 @@ Vous devriez écrire la méthode `render` sous forme de fonction pure, c'est-à- - `render` ne sera pas appelée si [`shouldComponentUpdate`](#shouldcomponentupdate) est définie et renvoie `false`. -* En [mode strict](/reference/react/StrictMode), React appellera `render` deux fois en développement et jettera un des résultats. Ça vous permet de repérer des effets de bord involontaires qui doivent être sortis de `render`. +* En [Mode Strict](/reference/react/StrictMode), React appellera `render` deux fois en développement et jettera un des résultats. Ça vous permet de repérer des effets de bord involontaires qui doivent être sortis de `render`. - Il n'y a pas de correspondance directe entre l'appel à `render` et les appels ultérieurs à `componentDidMount` et `componentDidUpdate`. Certains résultats d'appels à `render` sont susceptibles d'être ignorés par React lorsque ça présente un avantage. @@ -1223,7 +1223,7 @@ Par exemple, ce composant `ChatRoom` conserve une connexion au salon de discussi -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1253,7 +1253,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { Component } from 'react'; import { createConnection } from './chat.js'; @@ -1314,7 +1314,7 @@ export default class ChatRoom extends Component { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1335,7 +1335,7 @@ button { margin-left: 10px; } -Remarquez qu'en développement et lorsque le [mode strict](/reference/react/StrictMode) est actif, React appellera `componentDidMount`, puis appellera immédiatement `componentWillUnmount` et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique de `componentDidMount`. +Remarquez qu'en développement et lorsque le [Mode Strict](/reference/react/StrictMode) est actif, React appellera `componentDidMount`, puis appellera immédiatement `componentWillUnmount` et rappellera `componentDidMount` une seconde fois. Ça vous aide à remarquer un oubli d'implémentation de `componentWillUnmount`, ou un « miroir » insuffisant dans celle-ci de la logique de `componentDidMount`. @@ -1604,7 +1604,7 @@ Supposons que vous convertissiez ce composant à base de classe `ChatRoom`, dot -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1634,7 +1634,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { Component } from 'react'; import { createConnection } from './chat.js'; @@ -1695,7 +1695,7 @@ export default class ChatRoom extends Component { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1744,7 +1744,7 @@ Cet appel à [`useEffect`](/reference/react/useEffect) est équivalent à la log -```js App.js +```js src/App.js import { useState } from 'react'; import ChatRoom from './ChatRoom.js'; @@ -1774,7 +1774,7 @@ export default function App() { } ``` -```js ChatRoom.js active +```js src/ChatRoom.js active import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; @@ -1804,7 +1804,7 @@ export default function ChatRoom({ roomId }) { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { diff --git a/src/content/reference/react/Fragment.md b/src/content/reference/react/Fragment.md index 0579a3129..54ac5ad26 100644 --- a/src/content/reference/react/Fragment.md +++ b/src/content/reference/react/Fragment.md @@ -27,7 +27,7 @@ Enrobez des éléments dans un `` pour les grouper dans des situations #### Props {/*props*/} -- `key` **optionnel** : les fragments déclarés explicitement avec la syntaxe `` peuvent avoir une [keys](/learn/rendering-lists#keeping-list-items-in-order-with-key). +- `key` **optionnel** : les Fragments déclarés explicitement avec la syntaxe `` peuvent avoir une [keys](/learn/rendering-lists#keeping-list-items-in-order-with-key). #### Limitations {/*caveats*/} diff --git a/src/content/reference/react/StrictMode.md b/src/content/reference/react/StrictMode.md index 4a422e997..44adcd435 100644 --- a/src/content/reference/react/StrictMode.md +++ b/src/content/reference/react/StrictMode.md @@ -40,7 +40,7 @@ root.render( [Voir d'autres exemples plus bas](#usage). -Les comportements suivants sont activés en développement par le mode strict : +Les comportements suivants sont activés en développement par le Mode Strict : - Vos composants feront [un rendu supplémentaire](#fixing-bugs-found-by-double-rendering-in-development) afin de trouver les bugs causés par des rendus impurs. - Vos composants [exécuteront les Effets une fois supplémentaire](#fixing-bugs-found-by-re-running-effects-in-development) afin de détecter les bugs causés par l'absence de nettoyage d'Effet. @@ -52,18 +52,18 @@ Les comportements suivants sont activés en développement par le mode strict : #### Limitations {/*caveats*/} -* Il n'est pas possible de désactiver le mode strict au sein d'un arbre enrobé dans un ``. Ça vous garantit que tous les composants à l'intérieur de `` sont vérifiés. Si deux équipes travaillant sur un produit ne sont pas d'accord sur l'utilité de ces vérifications, elles doivent trouver un consensus ou déplacer le `` plus bas dans l'arbre. +* Il n'est pas possible de désactiver le Mode Strict au sein d'un arbre enrobé dans un ``. Ça vous garantit que tous les composants à l'intérieur de `` sont vérifiés. Si deux équipes travaillant sur un produit ne sont pas d'accord sur l'utilité de ces vérifications, elles doivent trouver un consensus ou déplacer le `` plus bas dans l'arbre. --- ## Utilisation {/*usage*/} -### Activer le mode strict pour toute l'appli {/*enabling-strict-mode-for-entire-app*/} +### Activer le Mode Strict pour toute l'appli {/*enabling-strict-mode-for-entire-app*/} -Le mode strict active des vérifications supplémentaires uniquement en mode de développement pour tout l'arbre des composants à l'intérieur du composant ``. Ces vérifications vous aident à trouver des bugs courants dans vos composants dès le début de la phase de développement. +Le Mode Strict active des vérifications supplémentaires uniquement en mode de développement pour tout l'arbre des composants à l'intérieur du composant ``. Ces vérifications vous aident à trouver des bugs courants dans vos composants dès le début de la phase de développement. -Pour activer le mode strict pour toute votre appli, enrobez votre composant racine avec `` lorsque vous en faites le rendu : +Pour activer le Mode Strict pour toute votre appli, enrobez votre composant racine avec `` lorsque vous en faites le rendu : ```js {6,8} import { StrictMode } from 'react'; @@ -77,13 +77,13 @@ root.render( ); ``` -Nous recommandons d'enrober toute votre appli dans le mode strict, en particulier pour les nouvelles applis. Si vous utilisez un framework qui appelle [`createRoot`](/reference/react-dom/client/createRoot) à votre place, consultez sa documentation pour savoir comment activer le mode strict. +Nous recommandons d'enrober toute votre appli dans le Mode Strict, en particulier pour les nouvelles applis. Si vous utilisez un framework qui appelle [`createRoot`](/reference/react-dom/client/createRoot) à votre place, consultez sa documentation pour savoir comment activer le Mode Strict. -Bien que les vérifications en mode strict **ne s'exécutent que durant le développement**, elles vous aident à trouver des bugs qui existent déjà dans votre code et qui peuvent être difficiles à reproduire de façon fiable en production. Le mode strict vous permet de corriger les bugs avant que vos utilisateurs ne les signalent. +Bien que les vérifications en Mode Strict **ne s'exécutent que durant le développement**, elles vous aident à trouver des bugs qui existent déjà dans votre code et qui peuvent être difficiles à reproduire de façon fiable en production. Le Mode Strict vous permet de corriger les bugs avant que vos utilisateurs ne les signalent. -Le mode strict active les vérifications suivantes en mode de développement : +Le Mode Strict active les vérifications suivantes en mode de développement : - Vos composants feront [un rendu supplémentaire](#fixing-bugs-found-by-double-rendering-in-development) afin de trouver les bugs causés par des rendus impurs. - Vos composants [exécuteront les Effets une fois supplémentaire](#fixing-bugs-found-by-re-running-effects-in-development) afin de détecter les bugs causés par l'absence de nettoyage d'Effet. @@ -95,9 +95,9 @@ Le mode strict active les vérifications suivantes en mode de développement : --- -### Activer le mode strict sur une partie de l'appli {/*enabling-strict-mode-for-a-part-of-the-app*/} +### Activer le Mode Strict sur une partie de l'appli {/*enabling-strict-mode-for-a-part-of-the-app*/} -Vous pouvez également activer le mode strict sur n'importe quelle partie de votre application : +Vous pouvez également activer le Mode Strict sur n'importe quelle partie de votre application : ```js {7,12} import { StrictMode } from 'react'; @@ -118,7 +118,7 @@ function App() { } ``` -Dans cet exemple, les vérifications du mode strict ne s'exécuteront pas sur les composants `Header` et `Footer`. Cependant, elles s'exécuteront sur `Sidebar` et `Content`, ainsi que sur tous les composants qu'ils contiennent, peu importe la profondeur à laquelle ils se trouvent. +Dans cet exemple, les vérifications du Mode Strict ne s'exécuteront pas sur les composants `Header` et `Footer`. Cependant, elles s'exécuteront sur `Sidebar` et `Content`, ainsi que sur tous les composants qu'ils contiennent, peu importe la profondeur à laquelle ils se trouvent. --- @@ -126,7 +126,7 @@ Dans cet exemple, les vérifications du mode strict ne s'exécuteront pas sur le [React part du principe que chaque composant que vous écrivez est une fonction pure](/learn/keeping-components-pure). Ça signifie que vos composants React doivent toujours renvoyer le même JSX pour les mêmes entrées (props, état et contexte). -Les composants qui ne respectent pas cette règle peuvent se comporter de façon imprévisible et occasionner des bugs. Pour vous aider à trouver du code accidentellement impur, le mode strict appelle certaines de vos fonctions (seulement celles qui doivent être pures) **deux fois en développement**. Ça inclut : +Les composants qui ne respectent pas cette règle peuvent se comporter de façon imprévisible et occasionner des bugs. Pour vous aider à trouver du code accidentellement impur, le Mode Strict appelle certaines de vos fonctions (seulement celles qui doivent être pures) **deux fois en développement**. Ça inclut : - Le corps de votre fonction composant (seulement la logique du niveau racine, ce qui exclut le code contenu dans les gestionnaires d'événements). - Les fonctions que vous passez à [`useState`](/reference/react/useState), aux [fonctions `set`](/reference/react/useState#setstate), à [`useMemo`](/reference/react/useMemo) ou à [`useReducer`](/reference/react/useReducer). @@ -134,13 +134,13 @@ Les composants qui ne respectent pas cette règle peuvent se comporter de façon Si une fonction est pure, l'exécuter deux fois ne change pas son comportement, car une telle fonction produit le même résultat à chaque fois. Cependant, si une fonction est impure (elle modifie par exemple la donnée qu'elle reçoit), l'exécuter deux fois devrait se remarquer (c'est ce qui la rend impure !). Ça vous aide à détecter et corriger les bugs plus rapidement. -**Voici un exemple qui illustre comment le double rendu en mode strict vous aide à détecter des bugs plus tôt.** +**Voici un exemple qui illustre comment le double rendu en Mode Strict vous aide à détecter des bugs plus tôt.** Ce composant `StoryTray` prend un tableau de `stories` et ajoute à la fin un élément « Créer une histoire » : -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -150,7 +150,7 @@ const root = createRoot(document.getElementById("root")); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -175,7 +175,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: 'Créer une histoire' }); @@ -218,7 +218,7 @@ Cette erreur devient bien plus facile à remarquer lorsque le composant `StoryTr -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -228,7 +228,7 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -253,7 +253,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active import { useState } from 'react'; export default function StoryTray({ stories }) { @@ -316,7 +316,7 @@ export default function StoryTray({ stories }) { -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -331,7 +331,7 @@ root.render( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -356,7 +356,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active export default function StoryTray({ stories }) { const items = stories; items.push({ id: 'create', label: 'Créer une histoire' }); @@ -393,11 +393,11 @@ li { -**Le mode strict appelle *toujours* votre fonction de rendu deux fois, afin que vous puissiez voir le problème immédiatement** (« Créer une histoire » apparaît deux fois). Ça vous permet de détecter ce genre d'erreur plus tôt dans le processus de développement. Lorsque vous corrigez votre composant pour qu'il fasse des rendus corrects en mode strict, vous corrigez *également* de nombreux bugs potentiels en production, telle que la fonctionnalité de survol précédente : +**Le Mode Strict appelle *toujours* votre fonction de rendu deux fois, afin que vous puissiez voir le problème immédiatement** (« Créer une histoire » apparaît deux fois). Ça vous permet de détecter ce genre d'erreur plus tôt dans le processus de développement. Lorsque vous corrigez votre composant pour qu'il fasse des rendus corrects en Mode Strict, vous corrigez *également* de nombreux bugs potentiels en production, telle que la fonctionnalité de survol précédente : -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -412,7 +412,7 @@ root.render( ); ``` -```js App.js +```js src/App.js import { useState } from 'react'; import StoryTray from './StoryTray.js'; @@ -437,7 +437,7 @@ export default function App() { } ``` -```js StoryTray.js active +```js src/StoryTray.js active import { useState } from 'react'; export default function StoryTray({ stories }) { @@ -483,7 +483,7 @@ li { -Sans le mode strict, il était facile de passer à côté du bug jusqu'à ce que vous ajoutiez d'autres rendus. Le mode strict fait apparaître le même bug immédiatement. Ce mode vous aide à trouver les bugs avant que vous ne les poussiez à votre équipe et à vos utilisateurs. +Sans le Mode Strict, il était facile de passer à côté du bug jusqu'à ce que vous ajoutiez d'autres rendus. Le Mode Strict fait apparaître le même bug immédiatement. Ce mode vous aide à trouver les bugs avant que vous ne les poussiez à votre équipe et à vos utilisateurs. [Apprenez-en davantage sur la façon de garder les composants purs](/learn/keeping-components-pure). @@ -497,19 +497,19 @@ Si vous avez installé [les outils de développement React](/learn/react-develop ### Corriger les bugs trouvés en réexécutant les Effets en développement {/*fixing-bugs-found-by-re-running-effects-in-development*/} -Le mode strict est également utile pour trouver des bugs dans les [Effets](/learn/synchronizing-with-effects). +Le Mode Strict est également utile pour trouver des bugs dans les [Effets](/learn/synchronizing-with-effects). Chaque Effet a du code d'initialisation et peut avoir du code de nettoyage. Normalement, React appelle le code d'initialisation quand le composant *est monté* (quand il est ajouté à l'écran), et appelle le code de nettoyage quand le composant est *démonté* (il est enlevé de l'écran). React appelle ensuite le nettoyage et l'initialisation à nouveau si l'une des dépendances de l'Effet a changé depuis le dernier rendu. -Quand le mode strict est activé, React exécutera **un cycle d'initialisation + nettoyage supplémentaire en développement pour chaque Effet**. Ça peut surprendre, mais ça aide à détecter des bugs subtils qu'il est difficile de repérer manuellement. +Quand le Mode Strict est activé, React exécutera **un cycle d'initialisation + nettoyage supplémentaire en développement pour chaque Effet**. Ça peut surprendre, mais ça aide à détecter des bugs subtils qu'il est difficile de repérer manuellement. -**Voici un exemple qui illustre comment la réexécution de l'Effet en mode strict vous aide à trouver des bugs plus rapidement.** +**Voici un exemple qui illustre comment la réexécution de l'Effet en Mode Strict vous aide à trouver des bugs plus rapidement.** Prenez cet exemple qui connecte un composant à un salon de discussion : -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -535,7 +535,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -568,7 +568,7 @@ Pour rendre le problème plus évident, ajoutons une fonctionnalité. Dans l'exe -```js index.js +```js src/index.js import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -619,7 +619,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -662,7 +662,7 @@ Maintenant que votre Effet « fait le nettoyage » et supprime les connexions -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -693,7 +693,7 @@ export default function ChatRoom() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -720,13 +720,13 @@ button { margin-left: 10px; } -**Avec le mode strict, vous voyez immédiatement qu'il y a un problème** (le nombre de connexions actives monte à 2). Ce mode exécute le cycle initialisation - nettoyage une fois de plus pour chaque Effet. Cet Effet n'a pas de logique de nettoyage, il crée donc une connexion supplémentaire sans jamais la détruire. C'est un indice qu'il vous manque une fonction de nettoyage. +**Avec le Mode Strict, vous voyez immédiatement qu'il y a un problème** (le nombre de connexions actives monte à 2). Ce mode exécute le cycle initialisation - nettoyage une fois de plus pour chaque Effet. Cet Effet n'a pas de logique de nettoyage, il crée donc une connexion supplémentaire sans jamais la détruire. C'est un indice qu'il vous manque une fonction de nettoyage. -Le mode strict vous permet de détecter de telles erreurs tôt dans le process. Lorsque vous corrigez votre Effet en ajoutant une fonction de nettoyage dans le mode strict, vous corrigez *également* de nombreux bugs potentiels en production, telle que la liste déroulante vue précédemment : +Le Mode Strict vous permet de détecter de telles erreurs tôt dans le process. Lorsque vous corrigez votre Effet en ajoutant une fonction de nettoyage dans le Mode Strict, vous corrigez *également* de nombreux bugs potentiels en production, telle que la liste déroulante vue précédemment : -```js index.js +```js src/index.js import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; @@ -783,7 +783,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js let connections = 0; export function createConnection(serverUrl, roomId) { @@ -812,13 +812,13 @@ button { margin-left: 10px; } Remarquez que le nombre de connexions actives dans la console cesse de grandir maintenant. -Sans le mode strict, il était facile de passer à côté du fait que l'Effet nécessitait une fonction de nettoyage. En exécutant *initialisation → nettoyage → initialisation* plutôt que *initialisation* de votre Effet en développement, le mode strict a rendu l'absence de fonction de nettoyage plus visible. +Sans le Mode Strict, il était facile de passer à côté du fait que l'Effet nécessitait une fonction de nettoyage. En exécutant *initialisation → nettoyage → initialisation* plutôt que *initialisation* de votre Effet en développement, le Mode Strict a rendu l'absence de fonction de nettoyage plus visible. [Apprenez-en davantage sur l'implémentation de fonction de nettoyage des Effets](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). --- -### Corriger les alertes de dépréciation activées par le mode strict {/*fixing-deprecation-warnings-enabled-by-strict-mode*/} +### Corriger les alertes de dépréciation activées par le Mode Strict {/*fixing-deprecation-warnings-enabled-by-strict-mode*/} React alerte si certains composants quelque part à l'intérieur de l'arbre de `` utilisent l'une de ces API dépréciées : diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 527712d54..ddfb585db 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -70,7 +70,7 @@ Dans l'exemple ci-dessous, le composant `Albums` *suspend* pendant qu'il charge } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -95,7 +95,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; @@ -115,7 +115,7 @@ function Loading() { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -165,7 +165,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -303,7 +303,7 @@ Dans l'exemple ci-dessous, les composants `Biography` et `Albums` chargent des d } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -328,7 +328,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; import Biography from './Biography.js'; @@ -353,7 +353,7 @@ function Loading() { } ``` -```js Panel.js +```js src/Panel.js export default function Panel({ children }) { return (
          @@ -363,7 +363,7 @@ export default function Panel({ children }) { } ``` -```js Biography.js hidden +```js src/Biography.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -409,7 +409,7 @@ function use(promise) { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -459,7 +459,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -632,7 +632,7 @@ La séquence sera : } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from 'react'; import ArtistPage from './ArtistPage.js'; @@ -657,7 +657,7 @@ export default function App() { } ``` -```js ArtistPage.js active +```js src/ArtistPage.js active import { Suspense } from 'react'; import Albums from './Albums.js'; import Biography from './Biography.js'; @@ -694,7 +694,7 @@ function AlbumsGlimmer() { } ``` -```js Panel.js +```js src/Panel.js export default function Panel({ children }) { return (
          @@ -704,7 +704,7 @@ export default function Panel({ children }) { } ``` -```js Biography.js hidden +```js src/Biography.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -750,7 +750,7 @@ function use(promise) { } ``` -```js Albums.js hidden +```js src/Albums.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -800,7 +800,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -955,7 +955,7 @@ Dans cet exemple, le composant `SearchResults` suspend pendant le chargement des } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import SearchResults from './SearchResults.js'; @@ -975,7 +975,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -1031,7 +1031,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -1181,7 +1181,7 @@ Tapez `"a"` dans l'exemple ci-dessous, attendez les résultats, puis modifiez vo } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -1205,7 +1205,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Note : ce composant est écrit au moyen d'une API expérimentale @@ -1261,7 +1261,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -1389,7 +1389,7 @@ Lorsqu'un composant suspend, le périmètre Suspense parent le plus proche bascu } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import IndexPage from './IndexPage.js'; import ArtistPage from './ArtistPage.js'; @@ -1437,7 +1437,7 @@ function BigSpinner() { } ``` -```js Layout.js +```js src/Layout.js export default function Layout({ children }) { return (
          @@ -1452,7 +1452,7 @@ export default function Layout({ children }) { } ``` -```js IndexPage.js +```js src/IndexPage.js export default function IndexPage({ navigate }) { return ( - +export default function App() { + return ( +
          + + +
          + ); } ``` diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index b4a0f83dc..c7e0dadbd 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -248,7 +248,7 @@ Puisque `Message` est enrobé dans un -```js message.js active +```js src/message.js active "use client"; import { use, Suspense } from "react"; @@ -267,7 +267,7 @@ export function MessageContainer({ messagePromise }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from "react"; import { MessageContainer } from "./message.js"; @@ -291,7 +291,7 @@ export default function App() { } ``` -```js index.js hidden +```js src/index.js hidden // TODO : remplacer l’import d’une version Canary // de React par une version stable, dès qu’elle // intégrera le Hook `use` @@ -367,7 +367,7 @@ Si vous souhaitez afficher une erreur à vos utilisateurs quand une promesse a -```js message.js active +```js src/message.js active "use client"; import { use, Suspense } from "react"; @@ -389,7 +389,7 @@ function Message({ messagePromise }) { } ``` -```js App.js hidden +```js src/App.js hidden import { useState } from "react"; import { MessageContainer } from "./message.js"; @@ -413,7 +413,7 @@ export default function App() { } ``` -```js index.js hidden +```js src/index.js hidden // TODO : remplacer l’import d’une version Canary // de React par une version stable, dès qu’elle // intégrera le Hook `use` diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 90a875495..17df2df6e 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -253,7 +253,7 @@ Essayez maintenant de basculer le thème. **Grâce à la combinaison de `useCall -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -280,7 +280,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import { useCallback } from 'react'; import ShippingForm from './ShippingForm.js'; @@ -306,7 +306,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { @@ -393,7 +393,7 @@ Contrairement à l'exemple précédent, la bascule du thème est désormais lent -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -420,7 +420,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import ShippingForm from './ShippingForm.js'; export default function ProductPage({ productId, referrer, theme }) { @@ -445,7 +445,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { @@ -526,7 +526,7 @@ Ceci dit, voici le même code **sans le ralentissement artificiel**. Est-ce que -```js App.js +```js src/App.js import { useState } from 'react'; import ProductPage from './ProductPage.js'; @@ -553,7 +553,7 @@ export default function App() { } ``` -```js ProductPage.js active +```js src/ProductPage.js active import ShippingForm from './ShippingForm.js'; export default function ProductPage({ productId, referrer, theme }) { @@ -578,7 +578,7 @@ function post(url, data) { } ``` -```js ShippingForm.js +```js src/ShippingForm.js import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { diff --git a/src/content/reference/react/useContext.md b/src/content/reference/react/useContext.md index ee97be878..42fd625f5 100644 --- a/src/content/reference/react/useContext.md +++ b/src/content/reference/react/useContext.md @@ -745,7 +745,7 @@ Lisez un [guide détaillé](/learn/scaling-up-with-reducer-and-context) de cet e -```js App.js +```js src/App.js import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; import { TasksProvider } from './TasksContext.js'; @@ -761,7 +761,7 @@ export default function TaskApp() { } ``` -```js TasksContext.js +```js src/TasksContext.js import { createContext, useContext, useReducer } from 'react'; const TasksContext = createContext(null); @@ -825,7 +825,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js +```js src/AddTask.js import { useState, useContext } from 'react'; import { useTasksDispatch } from './TasksContext.js'; @@ -854,7 +854,7 @@ export default function AddTask() { let nextId = 3; ``` -```js TaskList.js +```js src/TaskList.js import { useState, useContext } from 'react'; import { useTasks, useTasksDispatch } from './TasksContext.js'; @@ -1222,7 +1222,7 @@ export default function Page() { } ``` -```js Section.js +```js src/Section.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -1238,7 +1238,7 @@ export default function Section({ children }) { } ``` -```js Heading.js +```js src/Heading.js import { useContext } from 'react'; import { LevelContext } from './LevelContext.js'; @@ -1265,7 +1265,7 @@ export default function Heading({ children }) { } ``` -```js LevelContext.js +```js src/LevelContext.js import { createContext } from 'react'; export const LevelContext = createContext(0); diff --git a/src/content/reference/react/useDebugValue.md b/src/content/reference/react/useDebugValue.md index 11ca6c5d1..6c064a374 100644 --- a/src/content/reference/react/useDebugValue.md +++ b/src/content/reference/react/useDebugValue.md @@ -80,7 +80,7 @@ export default function App() { } ``` -```js useOnlineStatus.js active +```js src/useOnlineStatus.js active import { useSyncExternalStore, useDebugValue } from 'react'; export function useOnlineStatus() { diff --git a/src/content/reference/react/useDeferredValue.md b/src/content/reference/react/useDeferredValue.md index 5865c531a..9f8adc914 100644 --- a/src/content/reference/react/useDeferredValue.md +++ b/src/content/reference/react/useDeferredValue.md @@ -112,7 +112,7 @@ Dans cet exemple, le composant `SearchResults` [suspend](/reference/react/Suspen } ``` -```js App.js +```js src/App.js import { Suspense, useState } from 'react'; import SearchResults from './SearchResults.js'; @@ -132,7 +132,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Remarque : ce composant est écrit en utilisant une API expérimentale @@ -186,7 +186,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Remarque : la manière de récupérer les données dépend // du framework avec lequel vous utilisez Suspense. // En temps normal, la logique de cache est fournie par le framework. @@ -326,7 +326,7 @@ Tapez`"a"` dans l'exemple ci-dessous, attendez que les résultats soient chargé } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -347,7 +347,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Remarque : ce composant est écrit en utilisant une API expérimentale @@ -401,7 +401,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Remarque : la manière de récupérer les données dépend // du framework avec lequel vous utilisez Suspense. // En temps normal, la logique de cache est fournie par le framework. @@ -549,7 +549,7 @@ Avec ce changement, dès que vous commencerez à taper, l'ancienne liste de rés } ``` -```js App.js +```js src/App.js import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; @@ -576,7 +576,7 @@ export default function App() { } ``` -```js SearchResults.js hidden +```js src/SearchResults.js hidden import { fetchData } from './data.js'; // Remarque : ce composant est écrit en utilisant une API expérimentale @@ -630,7 +630,7 @@ function use(promise) { } ``` -```js data.js hidden +```js src/data.js hidden // Remarque : la manière de récupérer les données dépend // du framework avec lequel vous utilisez Suspense. // En temps normal, la logique de cache est fournie par le framework. @@ -799,7 +799,7 @@ export default function App() { } ``` -```js SlowList.js +```js src/SlowList.js import { memo } from 'react'; const SlowList = memo(function SlowList({ text }) { @@ -876,7 +876,7 @@ export default function App() { } ``` -```js SlowList.js +```js src/SlowList.js import { memo } from 'react'; const SlowList = memo(function SlowList({ text }) { diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md index 33661902f..f987b3175 100644 --- a/src/content/reference/react/useEffect.md +++ b/src/content/reference/react/useEffect.md @@ -58,7 +58,7 @@ function ChatRoom({ roomId }) { * Si vous **ne cherchez pas à synchroniser avec un système extérieur**, c'est que [vous n'avez probablement pas besoin d'un Effet](/learn/you-might-not-need-an-effect). -* Quand le mode strict est activé, React **appellera une fois de plus votre cycle mise en place + nettoyage, uniquement en développement**, avant la première mise en place réelle. C'est une mise à l'épreuve pour vérifier que votre logique de nettoyage reflète bien votre logique de mise en place, et décommissionne ou défait toute la mise en place effectuée. Si ça entraîne des problèmes, [écrivez une fonction de nettoyage](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). +* Quand le Mode Strict est activé, React **appellera une fois de plus votre cycle mise en place + nettoyage, uniquement en développement**, avant la première mise en place réelle. C'est une mise à l'épreuve pour vérifier que votre logique de nettoyage reflète bien votre logique de mise en place, et décommissionne ou défait toute la mise en place effectuée. Si ça entraîne des problèmes, [écrivez une fonction de nettoyage](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). * Si certaines de vos dépendances sont des objets ou fonctions définies au sein de votre composant, il existe un risque qu'elles **entraînent des exécutions superflues de votre Effet**. Pour corriger ça, retirez les dépendances superflues sur des [objets](#removing-unnecessary-object-dependencies) et [fonctions](#removing-unnecessary-function-dependencies). Vous pouvez aussi [extraire les mises à jour d'état](#updating-state-based-on-previous-state-from-an-effect) et la [logique non réactive](#reading-the-latest-props-and-state-from-an-effect) hors de votre Effet. @@ -193,7 +193,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -317,7 +317,7 @@ export default function App() { } ``` -```js animation.js +```js src/animation.js export class FadeInAnimation { constructor(node) { this.node = node; @@ -393,7 +393,7 @@ export default function App() { } ``` -```js ModalDialog.js active +```js src/ModalDialog.js active import { useEffect, useRef } from 'react'; export default function ModalDialog({ isOpen, children }) { @@ -454,7 +454,7 @@ function LongSection() { } ``` -```js Box.js active +```js src/Box.js active import { useRef, useEffect } from 'react'; export default function Box() { @@ -597,7 +597,7 @@ export default function App() { } ``` -```js useChatRoom.js +```js src/useChatRoom.js import { useEffect } from 'react'; import { createConnection } from './chat.js'; @@ -612,7 +612,7 @@ export function useChatRoom({ serverUrl, roomId }) { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -669,7 +669,7 @@ export default function App() { } ``` -```js useWindowListener.js +```js src/useWindowListener.js import { useState, useEffect } from 'react'; export function useWindowListener(eventType, listener) { @@ -722,7 +722,7 @@ function LongSection() { } ``` -```js Box.js active +```js src/Box.js active import { useRef, useEffect } from 'react'; import { useIntersectionObserver } from './useIntersectionObserver.js'; @@ -752,7 +752,7 @@ export default function Box() { } ``` -```js useIntersectionObserver.js +```js src/useIntersectionObserver.js import { useState, useEffect } from 'react'; export function useIntersectionObserver(ref) { @@ -810,7 +810,7 @@ Imaginons par exemple que vous ayez un widget tiers de cartographie, ou un compo } ``` -```js App.js +```js src/App.js import { useState } from 'react'; import Map from './Map.js'; @@ -828,7 +828,7 @@ export default function App() { } ``` -```js Map.js active +```js src/Map.js active import { useRef, useEffect } from 'react'; import { MapWidget } from './map-widget.js'; @@ -854,7 +854,7 @@ export default function Map({ zoomLevel }) { } ``` -```js map-widget.js +```js src/map-widget.js import 'leaflet/dist/leaflet.css'; import * as L from 'leaflet'; @@ -926,7 +926,7 @@ Remarquez la variable `ignore`, qui est initialisée à `false` mais mise à `tr -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchBio } from './api.js'; @@ -962,7 +962,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { @@ -979,7 +979,7 @@ Vous pouvez aussi le réécrire en utilisant la syntaxe [`async` / `await`](http -```js App.js +```js src/App.js import { useState, useEffect } from 'react'; import { fetchBio } from './api.js'; @@ -1018,7 +1018,7 @@ export default function Page() { } ``` -```js api.js hidden +```js src/api.js hidden export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { @@ -1214,7 +1214,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1294,7 +1294,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1387,7 +1387,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection(serverUrl, roomId) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1550,7 +1550,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1661,7 +1661,7 @@ export default function App() { } ``` -```js chat.js +```js src/chat.js export function createConnection({ serverUrl, roomId }) { // Une véritable implémentation se connecterait en vrai au serveur return { @@ -1763,7 +1763,7 @@ N'abusez pas de cette astuce. Gardez à l'esprit que les utilisateurs avec des ### Mon Effet est exécuté deux fois au montage du composant {/*my-effect-runs-twice-when-the-component-mounts*/} -Lorsque le mode strict est activé, en développement, React exécutera une première fois la mise en place et le nettoyage, avant la mise en place effective. +Lorsque le Mode Strict est activé, en développement, React exécutera une première fois la mise en place et le nettoyage, avant la mise en place effective. C'est une mise à l'épreuve pour vérifier que la logique de votre Effet est implémentée correctement. Si ça entraîne des problèmes, c'est que votre code de nettoyage est manquant ou incomplet. La fonction de nettoyage devrait arrêter ou défaire ce que la fonction de mise en place a initié. La règle à suivre est simple : l'utilisateur ne devrait pas pouvoir faire la différence entre une exécution unique de la mise en place (comme en production) et une séquence *mise en place* → *nettoyage* → *mise en place* (comme en développement). diff --git a/src/content/reference/react/useId.md b/src/content/reference/react/useId.md index 0d91d59e3..ceb1f5382 100644 --- a/src/content/reference/react/useId.md +++ b/src/content/reference/react/useId.md @@ -269,7 +269,7 @@ export default function App() { } ``` -```js index.js active +```js src/index.js active import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; @@ -302,3 +302,33 @@ input { margin: 5px; } ``` + +--- + +### Utiliser le même préfixe d'identifiant côtés client et serveur {/*using-the-same-id-prefix-on-the-client-and-the-server*/} + +Si vous [injectez plusieurs applis React distinctes sur la même page](#specifying-a-shared-prefix-for-all-generated-ids) et que certaines de ces applis bénéficient d'un rendu côté serveur, assurez-vous que le `identifierPrefix` passé à [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) côté client est identique au `identifierPrefix` passé aux [API côté serveur](/reference/react-dom/server), telles que [`renderToPipeableStream`](/reference/react-dom/server/renderToPipeableStream). + +```js +// Serveur +import { renderToPipeableStream } from 'react-dom/server'; + +const { pipe } = renderToPipeableStream( + , + { identifierPrefix: 'react-app1' } +); +``` + +```js +// Client +import { hydrateRoot } from 'react-dom/client'; + +const domNode = document.getElementById('root'); +const root = hydrateRoot( + domNode, + reactNode, + { identifierPrefix: 'react-app1' } +); +``` + +Vous n'avez besoin de passer un `identifierPrefix` que si vous avez plus d'une appli React sur la page. diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index ca3d745cb..1f13bd0c6 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -133,7 +133,7 @@ export default function Form() { } ``` -```js MyInput.js +```js src/MyInput.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { @@ -194,7 +194,7 @@ export default function Page() { } ``` -```js Post.js +```js src/Post.js import { forwardRef, useRef, useImperativeHandle } from 'react'; import CommentList from './CommentList.js'; import AddComment from './AddComment.js'; @@ -227,7 +227,7 @@ export default Post; ``` -```js CommentList.js +```js src/CommentList.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const CommentList = forwardRef(function CommentList(props, ref) { @@ -257,7 +257,7 @@ const CommentList = forwardRef(function CommentList(props, ref) { export default CommentList; ``` -```js AddComment.js +```js src/AddComment.js import { forwardRef, useRef, useImperativeHandle } from 'react'; const AddComment = forwardRef(function AddComment(props, ref) { diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index c18990964..89835ef05 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -59,7 +59,7 @@ function Tooltip() { * `useLayoutEffect` est un Hook, vous pouvez donc uniquement l’appeler **à la racine de votre composant** ou de vos propres Hooks. Vous ne pouvez pas l’appeler à l’intérieur de boucles ou de conditions. Si nécessaire, extrayez un nouveau composant et déplacez l'Effet dans celui-ci. -* Quand le mode strict est activé, React **appellera une fois de plus votre cycle mise en place + nettoyage, uniquement en développement**, avant la première mise en place réelle. C'est une mise à l'épreuve pour vérifier que votre logique de nettoyage reflète bien votre logique de mise en place, et décommissionne ou défait toute la mise en place effectuée. Si ça entraîne des problèmes, [écrivez une fonction de nettoyage](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). +* Quand le Mode Strict est activé, React **appellera une fois de plus votre cycle mise en place + nettoyage, uniquement en développement**, avant la première mise en place réelle. C'est une mise à l'épreuve pour vérifier que votre logique de nettoyage reflète bien votre logique de mise en place, et décommissionne ou défait toute la mise en place effectuée. Si ça entraîne des problèmes, [écrivez une fonction de nettoyage](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). * Si certaines de vos dépendances sont des objets ou fonctions définies au sein de votre composant, il existe un risque qu'elles **entraînent des exécutions superflues de votre Effet**. Pour corriger ça, retirez les dépendances superflues sur des [objets](#removing-unnecessary-object-dependencies) et [fonctions](#removing-unnecessary-function-dependencies). Vous pouvez aussi [extraire les mises à jour d'état](#updating-state-based-on-previous-state-from-an-effect) et la [logique non réactive](#reading-the-latest-props-and-state-from-an-effect) hors de votre Effet. @@ -149,7 +149,7 @@ export default function App() { } ``` -```js ButtonWithTooltip.js +```js src/ButtonWithTooltip.js import { useState, useRef } from 'react'; import Tooltip from './Tooltip.js'; @@ -185,7 +185,7 @@ export default function ButtonWithTooltip({ tooltipContent, ...rest }) { } ``` -```js Tooltip.js active +```js src/Tooltip.js active import { useRef, useLayoutEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import TooltipContainer from './TooltipContainer.js'; @@ -220,7 +220,7 @@ export default function Tooltip({ children, targetRect }) { } ``` -```js TooltipContainer.js +```js src/TooltipContainer.js export default function TooltipContainer({ children, x, y, contentRef }) { return (
          @@ -180,7 +180,7 @@ Essayez maintenant de basculer le thème. **Grâce à `useMemo`, c'est rapide en -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -222,7 +222,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { useMemo } from 'react'; import { filterTodos } from './utils.js' @@ -249,7 +249,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -310,7 +310,7 @@ Contrairement à l'exemple précédent, la bascule du thème est désormais lent -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -352,7 +352,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { @@ -375,7 +375,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -430,7 +430,7 @@ Ceci dit, voici le même code **sans le ralentissement artificiel**. Est-ce que -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -472,7 +472,7 @@ export default function App() { ``` -```js TodoList.js active +```js src/TodoList.js active import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { @@ -494,7 +494,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -654,7 +654,7 @@ Essayez maintenant de basculer le thème. **Grâce à la combinaison de `useMemo -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -695,7 +695,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useMemo } from 'react'; import List from './List.js'; import { filterTodos } from './utils.js' @@ -714,7 +714,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; const List = memo(function List({ items }) { @@ -741,7 +741,7 @@ const List = memo(function List({ items }) { export default List; ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -796,7 +796,7 @@ Contrairement à l'exemple précédent, la bascule du thème est désormais lent -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -837,7 +837,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import List from './List.js'; import { filterTodos } from './utils.js' @@ -852,7 +852,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; const List = memo(function List({ items }) { @@ -879,7 +879,7 @@ const List = memo(function List({ items }) { export default List; ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -928,7 +928,7 @@ Ceci dit, voici le même code **sans le ralentissement artificiel**. Est-ce que -```js App.js +```js src/App.js import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; @@ -969,7 +969,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import List from './List.js'; import { filterTodos } from './utils.js' @@ -983,7 +983,7 @@ export default function TodoList({ todos, theme, tab }) { } ``` -```js List.js +```js src/List.js import { memo } from 'react'; function List({ items }) { @@ -1004,7 +1004,7 @@ function List({ items }) { export default memo(List); ``` -```js utils.js +```js src/utils.js export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { @@ -1163,7 +1163,7 @@ Ces deux exemples sont parfaitement équivalents. Le seul avantage de `useCallb ### Mon calcul est exécuté deux fois par rendu {/*my-calculation-runs-twice-on-every-re-render*/} -En [mode strict](/reference/react/StrictMode), React appellera certaines de vos fonctions deux fois plutôt qu'une : +En [Mode Strict](/reference/react/StrictMode), React appellera certaines de vos fonctions deux fois plutôt qu'une : ```js {2,5,6} function TodoList({ todos, tab }) { diff --git a/src/content/reference/react/useOptimistic.md b/src/content/reference/react/useOptimistic.md index e3859db5e..93fd5bfc9 100644 --- a/src/content/reference/react/useOptimistic.md +++ b/src/content/reference/react/useOptimistic.md @@ -71,7 +71,7 @@ Lorsqu'un utilisateur saisit par exemple un message dans un formulaire puis cliq -```js App.js +```js src/App.js import { useOptimistic, useState, useRef } from "react"; import { deliverMessage } from "./actions.js"; @@ -121,7 +121,7 @@ export default function App() { } ``` -```js actions.js +```js src/actions.js export async function deliverMessage(message) { await new Promise((res) => setTimeout(res, 1000)); return message; diff --git a/src/content/reference/react/useReducer.md b/src/content/reference/react/useReducer.md index e7baaeb8d..01a419573 100644 --- a/src/content/reference/react/useReducer.md +++ b/src/content/reference/react/useReducer.md @@ -52,7 +52,7 @@ function MyComponent() { #### Limitations {/*caveats*/} * `useReducer` est un Hook, vous ne pouvez donc l'appeler **qu'au niveau racine de votre composant** ou dans vos propres Hooks. Vous ne pouvez pas l'appeler dans des boucles ou des conditions. Si vous avez besoin de le faire, extrayez un nouveau composant et déplacez-y l'état. -* En mode strict, React **appellera deux fois votre réducteur et votre fonction d'initialisation** afin de [vous aider à détecter des impuretés accidentelles](#my-reducer-or-initializer-function-runs-twice). Ce comportement est limité au développement et n'affecte pas la production. Si votre réducteur et votre fonction d'initialisation sont pures (ce qui devrait être le cas), ça n'impactera pas votre logique. Le résultat de l'un des appels est ignoré. +* En Mode Strict, React **appellera deux fois votre réducteur et votre fonction d'initialisation** afin de [vous aider à détecter des impuretés accidentelles](#my-reducer-or-initializer-function-runs-twice). Ce comportement est limité au développement et n'affecte pas la production. Si votre réducteur et votre fonction d'initialisation sont pures (ce qui devrait être le cas), ça n'impactera pas votre logique. Le résultat de l'un des appels est ignoré. --- @@ -322,7 +322,7 @@ Dans cet exemple, le réducteur gère un tableau de tâches. Le tableau doit êt -```js App.js +```js src/App.js import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -405,7 +405,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -426,7 +426,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -515,7 +515,7 @@ S'il est fastidieux de mettre à jour les tableaux et les objets sans les modifi -```js App.js +```js src/App.js import { useImmerReducer } from 'use-immer'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; @@ -597,7 +597,7 @@ const initialTasks = [ ]; ``` -```js AddTask.js hidden +```js src/AddTask.js hidden import { useState } from 'react'; export default function AddTask({ onAddTask }) { @@ -618,7 +618,7 @@ export default function AddTask({ onAddTask }) { } ``` -```js TaskList.js hidden +```js src/TaskList.js hidden import { useState } from 'react'; export default function TaskList({ @@ -763,7 +763,7 @@ Cet exemple passe la fonction d'initialisation, la fonction `createInitialState` -```js App.js hidden +```js src/App.js hidden import TodoList from './TodoList.js'; export default function App() { @@ -771,7 +771,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useReducer } from 'react'; function createInitialState(username) { @@ -851,7 +851,7 @@ Cet exemple **ne passe pas** la fonction d'initialisation, donc la fonction `cre -```js App.js hidden +```js src/App.js hidden import TodoList from './TodoList.js'; export default function App() { @@ -859,7 +859,7 @@ export default function App() { } ``` -```js TodoList.js active +```js src/TodoList.js active import { useReducer } from 'react'; function createInitialState(username) { @@ -1083,7 +1083,7 @@ Si vous ne trouvez pas la cause de cette erreur, cliquez sur la flèche à côt ### Mon réducteur ou ma fonction d'initialisation s'exécute deux fois {/*my-reducer-or-initializer-function-runs-twice*/} -En [mode strict](/reference/react/StrictMode), React appellera votre réducteur et votre fonction d'initialisation deux fois. Ça ne devrait pas casser votre code. +En [Mode Strict](/reference/react/StrictMode), React appellera votre réducteur et votre fonction d'initialisation deux fois. Ça ne devrait pas casser votre code. Ce comportement **spécifique au développement** vous aide à [garder les composants purs](/learn/keeping-components-pure). React utilise le résultat de l'un des appels et ignore l'autre. Tant que votre composant, votre fonction d'initialisation et votre réducteur sont purs, ça ne devrait pas affecter votre logique. Si toutefois ils sont malencontreusement impurs, ça vous permettra de détecter les erreurs. diff --git a/src/content/reference/react/useRef.md b/src/content/reference/react/useRef.md index 49fb515b3..fd7268385 100644 --- a/src/content/reference/react/useRef.md +++ b/src/content/reference/react/useRef.md @@ -50,7 +50,7 @@ Lors des rendus ultérieurs, `useRef` renverra le même objet. * Vous pouvez modifier la propriété `ref.current`. Contrairement à l'état, elle est modifiable. En revanche, si vous y stockez un objet nécessaire au rendu (par exemple un morceau de votre état), vous ne devriez pas modifier cet objet. * Lorsque vous modifiez la propriété `ref.current`, React ne refait pas de rendu de votre composant. React n'est pas au courant de vos modifications parce qu'une ref est un objet JavaScript brut. * Évitez d'écrire _ou même de lire_ `ref.current` lors du rendu, sauf pour [l'initialiser](#avoiding-recreating-the-ref-contents). Ça rendrait le comportement de votre composant imprévisible. -* En mode strict, React **appellera votre fonction composant deux fois** afin de [vous aider à repérer des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est limité au développement et n'affecte pas la production. Chaque objet ref sera créé deux fois, mais une de ses versions sera ignorée. Si votre fonction composant est pure (ce qui devrait être le cas), ça n'affectera en rien son comportement. +* En Mode Strict, React **appellera votre fonction composant deux fois** afin de [vous aider à repérer des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est limité au développement et n'affecte pas la production. Chaque objet ref sera créé deux fois, mais une de ses versions sera ignorée. Si votre fonction composant est pure (ce qui devrait être le cas), ça n'affectera en rien son comportement. --- diff --git a/src/content/reference/react/useState.md b/src/content/reference/react/useState.md index a8605a806..96aa98af8 100644 --- a/src/content/reference/react/useState.md +++ b/src/content/reference/react/useState.md @@ -51,7 +51,7 @@ La convention est de nommer les variables d'états de cette manière : `[someth #### Limitations {/*caveats*/} * `useState` est un Hook, vous ne pouvez donc l’appeler qu'**à la racine de votre composant** ou de vos propres Hooks. Vous ne pouvez pas l’appeler à l’intérieur de boucles ou de conditions. Si nécessaire, extrayez un nouveau composant et déplacez l'état dans celui-ci. -* En mode strict, React **appellera votre fonction d'initialisation deux fois** afin de vous aider à [détecter des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est uniquement présent en mode développement et n'affecte pas la production. Si votre fonction d'initialisation est pure (ce qui devrait être le cas), ça ne devrait pas affecter le comportement. Le résultat d'un des appels sera ignoré. +* En Mode Strict, React **appellera votre fonction d'initialisation deux fois** afin de vous aider à [détecter des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est uniquement présent en mode développement et n'affecte pas la production. Si votre fonction d'initialisation est pure (ce qui devrait être le cas), ça ne devrait pas affecter le comportement. Le résultat d'un des appels sera ignoré. --- @@ -87,7 +87,7 @@ Les fonctions de mise à jour (celles renvoyées par `useState`) n'ont pas de va * Il est possible d'appeler la fonction de mise à jour *pendant le rendu*, mais uniquement au sein du composant en cours de rendu. React ignorera le JSX résultat pour refaire immédiatement un rendu avec le nouvel état. Cette approche est rarement nécessaire, mais vous pouvez l'utiliser pour **stocker des informations des précédents rendus**. [Voir un exemple ci-dessous](#storing-information-from-previous-renders). -* En mode strict, React **appellera votre fonction d'initialisation deux fois** afin de vous aider à [détecter des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est spécifique au mode développement et n'affecte pas la production. Si votre fonction de mise à jour est pure (ce qui devrait être le cas), ça ne devrait pas affecter le comportement. Le résultat d'un des appels sera ignoré. +* En Mode Strict, React **appellera votre fonction d'initialisation deux fois** afin de vous aider à [détecter des impuretés accidentelles](#my-initializer-or-updater-function-runs-twice). Ce comportement est spécifique au mode développement et n'affecte pas la production. Si votre fonction de mise à jour est pure (ce qui devrait être le cas), ça ne devrait pas affecter le comportement. Le résultat d'un des appels sera ignoré. --- @@ -630,7 +630,7 @@ Dans cet exemple, la variable d'état `todos` contient un tableau. Chaque gestio -```js App.js +```js src/App.js import { useState } from 'react'; import AddTodo from './AddTodo.js'; import TaskList from './TaskList.js'; @@ -687,7 +687,7 @@ export default function TaskApp() { } ``` -```js AddTodo.js +```js src/AddTodo.js import { useState } from 'react'; export default function AddTodo({ onAddTodo }) { @@ -708,7 +708,7 @@ export default function AddTodo({ onAddTodo }) { } ``` -```js TaskList.js +```js src/TaskList.js import { useState } from 'react'; export default function TaskList({ @@ -1028,7 +1028,7 @@ Consultez [Préserver et réinitialiser l'état](/learn/preserving-and-resetting -```js App.js +```js src/App.js import { useState } from 'react'; export default function App() { @@ -1083,7 +1083,7 @@ Dans de rares autres cas, il existe une approche que vous pouvez utiliser pour m Voici un exemple. Ce composant `CountLabel` affiche une prop `count` qui lui est passée : -```js CountLabel.js +```js src/CountLabel.js export default function CountLabel({ count }) { return

          {count}

          } @@ -1093,7 +1093,7 @@ Mettons que vous vouliez indiquer si le compteur a *augmenté ou diminué* depui -```js App.js +```js src/App.js import { useState } from 'react'; import CountLabel from './CountLabel.js'; @@ -1113,7 +1113,7 @@ export default function App() { } ``` -```js CountLabel.js active +```js src/CountLabel.js active import { useState } from 'react'; export default function CountLabel({ count }) { @@ -1219,7 +1219,7 @@ Si vous n'arrivez pas à trouver le cause de cette erreur, cliquez dans la conso ### Ma fonction d'initialisation (ou de mise à jour) est exécutée deux fois {/*my-initializer-or-updater-function-runs-twice*/} -En [mode strict](/reference/react/StrictMode), React appellera certaines de vos fonctions plutôt deux fois qu'une : +En [Mode Strict](/reference/react/StrictMode), React appellera certaines de vos fonctions plutôt deux fois qu'une : ```js {2,5-6,11-12} function TodoList() { diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index 3b85ca7b0..a3491fc35 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -57,9 +57,9 @@ L'instantané actuel de la valeur issue de la source, que vous pouvez utiliser p * Si une fonction `subscribe` différente est passée lors d'un nouveau rendu, React se réabonnera à la source de données en utilisant cette nouvelle fonction `subscribe`. Vous pouvez éviter ça en déclarant `subscribe` hors du composant. -* Si la source est modifiée au sein d'une [transition non bloquante](/reference/react/useTransition), React se rabattra sur une application bloquante de la mise à jour. Plus spécifiquement, React rappellera `getSnapshot` juste avant d'appliquer les modifications au DOM. Si la valeur renvoyée diffère de celle produite par le premier appel, React redémarrera le processus de transition de zéro, en l'appliquant cette fois en tant que mise à jour bloquante, pour garantir que chaque composant à l'écran reflète bien la même version de la source. +* Si la source est modifiée au sein d'une [transition non bloquante](/reference/react/useTransition), React se rabattra sur une application bloquante de la mise à jour. Plus spécifiquement, pour chaque mise à jour au sein de la transition, React rappellera `getSnapshot` juste avant d'appliquer les modifications au DOM. Si la valeur renvoyée diffère de celle produite par le premier appel, React redémarrera le processus de transition de zéro, en l'appliquant cette fois en tant que mise à jour bloquante, pour garantir que chaque composant à l'écran reflète bien la même version de la source. -* Nous vous déconseillons de _suspendre_ un rendu basé sur une valeur de la source renvoyée par `useSyncExternalStore`. Ça vient de ce que les mutations de la source ne peuvent pas être [marquées comme des transitions non bloquantes](/reference/react/useTransition), et déclencheront donc le plus proche [affichage de secours `Suspense`](/reference/react/Suspense), remplaçant ainsi du contenu déjà affiché avec un écran montrant un indicateur de chargement, ce qui est généralement indésirable en termes d'UX. +* Nous vous déconseillons de _suspendre_ un rendu basé sur une valeur de la source renvoyée par `useSyncExternalStore`. Ça vient de ce que les mutations de la source ne peuvent pas être marquées comme des [transitions non bloquantes](/reference/react/useTransition), et déclencheront donc le plus proche [affichage de secours `Suspense`](/reference/react/Suspense), remplaçant ainsi du contenu déjà affiché avec un écran montrant un indicateur de chargement, ce qui est généralement indésirable en termes d'UX. À titre d'exemple, le code suivant est déconseillé : @@ -131,7 +131,7 @@ export default function TodosApp() { } ``` -```js todoStore.js +```js src/todoStore.js // Voici un exemple de source de données tierce // que vous pourriez avoir besoin d'intégrer dans React. @@ -300,7 +300,7 @@ export default function App() { } ``` -```js useOnlineStatus.js +```js src/useOnlineStatus.js import { useSyncExternalStore } from 'react'; export function useOnlineStatus() { diff --git a/src/content/reference/react/useTransition.md b/src/content/reference/react/useTransition.md index f5f2d8179..b3f2da5d7 100644 --- a/src/content/reference/react/useTransition.md +++ b/src/content/reference/react/useTransition.md @@ -184,7 +184,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -202,7 +202,7 @@ export default function TabButton({ children, isActive, onClick }) { ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -210,7 +210,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -245,7 +245,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -321,7 +321,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -339,7 +339,7 @@ export default function TabButton({ children, isActive, onClick }) { ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -347,7 +347,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -382,7 +382,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -475,7 +475,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -495,7 +495,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -503,7 +503,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -538,7 +538,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -619,7 +619,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -642,7 +642,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js +```js src/AboutTab.js export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -650,7 +650,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js +```js src/PostsTab.js import { memo } from 'react'; const PostsTab = memo(function PostsTab() { @@ -685,7 +685,7 @@ function SlowPost({ index }) { export default PostsTab; ``` -```js ContactTab.js +```js src/ContactTab.js export default function ContactTab() { return ( <> @@ -755,7 +755,7 @@ export default function TabContainer() { } ``` -```js TabButton.js +```js src/TabButton.js export default function TabButton({ children, isActive, onClick }) { if (isActive) { return {children} @@ -770,7 +770,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js hidden +```js src/AboutTab.js hidden export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -778,7 +778,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js hidden +```js src/PostsTab.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -836,7 +836,7 @@ function use(promise) { } ``` -```js ContactTab.js hidden +```js src/ContactTab.js hidden export default function ContactTab() { return ( <> @@ -853,7 +853,7 @@ export default function ContactTab() { ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -943,7 +943,7 @@ export default function TabContainer() { } ``` -```js TabButton.js active +```js src/TabButton.js active import { useTransition } from 'react'; export default function TabButton({ children, isActive, onClick }) { @@ -966,7 +966,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -```js AboutTab.js hidden +```js src/AboutTab.js hidden export default function AboutTab() { return (

          Bienvenue sur mon profil !

          @@ -974,7 +974,7 @@ export default function AboutTab() { } ``` -```js PostsTab.js hidden +```js src/PostsTab.js hidden import { fetchData } from './data.js'; // Note: this component is written using an experimental API @@ -1032,7 +1032,7 @@ function use(promise) { } ``` -```js ContactTab.js hidden +```js src/ContactTab.js hidden export default function ContactTab() { return ( <> @@ -1049,7 +1049,7 @@ export default function ContactTab() { ``` -```js data.js hidden +```js src/data.js hidden // Note : la façon de charger vos données dépend du framework // que vous utilisez en complément de Suspense. // Normalement, la logique de cache serait fournie par le framework. @@ -1146,7 +1146,7 @@ Voici un petit exemple de routeur très simplifié utilisant les transitions pou } ``` -```js App.js +```js src/App.js import { Suspense, useState, useTransition } from 'react'; import IndexPage from './IndexPage.js'; import ArtistPage from './ArtistPage.js'; @@ -1197,7 +1197,7 @@ function BigSpinner() { } ``` -```js Layout.js +```js src/Layout.js export default function Layout({ children, isPending }) { return (
          @@ -1214,7 +1214,7 @@ export default function Layout({ children, isPending }) { } ``` -```js IndexPage.js +```js src/IndexPage.js export default function IndexPage({ navigate }) { return ( + }} + > + Ajouter un commentaire + ); } ``` -```js App.js hidden +```js src/App.js hidden import { AddCommentContainer } from "./AddCommentContainer.js"; export default function App() { @@ -1571,7 +1572,7 @@ export default function App() { } ``` -```js index.js hidden +```js src/index.js hidden // TODO: mettre à jour l'import vers la version stable de React // une fois que le Hook `use` actuellement Canary y figurera import React, { StrictMode } from 'react'; diff --git a/yarn.lock b/yarn.lock index c7b0f980e..2978fc7b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1619,20 +1619,10 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001301" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz#ebc9086026534cab0dab99425d9c3b4425e5f450" - integrity sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA== - -caniuse-lite@^1.0.30001370: - version "1.0.30001390" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001390.tgz#158a43011e7068ef7fc73590e9fd91a7cece5e7f" - integrity sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g== - -caniuse-lite@^1.0.30001406: - version "1.0.30001410" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001410.tgz#b5a86366fbbf439d75dd3db1d21137a73e829f44" - integrity sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ== +caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001370, caniuse-lite@^1.0.30001406: + version "1.0.30001572" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz" + integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw== ccount@^1.0.0: version "1.1.0"