# React 101 --- ## Objectif de la capsule Être capable de développer un projet en React --- ## Programme - Présentation - Construire son UI - La rendre interactive - Les systèmes externes - Optimisation - L'écosystème # Présentation --- # My name is Act, React! - Une bibliothèque JS pour construire des apps web - Par Facebook --- ## Forces - Écosystème Large - Composants Réutilisables - Flexibilité - One-Way Data Flow - Virtual DOM - « Easy to learn... » - Pas que pour le HTML --- ## Pas du HTML ? - React native - Remotion - React Three Fiber - React PDF - React Figma --- ## Faiblesses - Virtual DOM - « ...hard to master » - Optimisation des perfs parfois difficile --- ## React vs les autres - Une bibliothèque pas un framework - Plus de liberté... - ...trop de liberté --- ## Liens - https://react.dev - https://github.com/enaqx/awesome-react # Let's get started --- ## Un composant - Une fonction JS - Qui retourne du DOM --- ## Exemple ```js const MyFirstComponent = () => { return
Bonjour
monde!!
} ``` --- ## WTF, du HTML dans du JS ????? - Du JSX - Doit être transpilé - Pas obligatoire --- ## Mais pourquoi ? - Un retour en arrière ? - Tout en un - Code plus lisible - JS as template --- ## Sans JSX ? - Avec [React.createElement](minimal/minimal_htm.html) - Avec [htm](minimal/minimal_htm.html) - ou une autre lib de template html --- ## Revenons à nos poissons - Attention à la majuscule - Exporter la fonction - Ne pas *nester* la definition d'un composant [À vous](https://react.dev/learn/your-first-component#challenges) Note: - Capital letter # Interface utilisateur --- ## JSX - Un seul élément root : - -> fragment `<>>` - Fermer tous les tags - CamelCase pour les attributs - Multi ligne avec `()` [À vous](https://react.dev/learn/writing-markup-with-jsx#challenges) --- ## Faire un sous composant Simplement l'appeler dans le JSX ```js function MyOtherComponent() { return
N7
} export default function Component() { return
Bonjour
!
} ``` [À vous](https://codesandbox.io/p/sandbox/multiple-components-ysw3fw) Et dans un autre fichier? --- ## Inline JS Code js entre `{}` ```js return (
{content}
{myFunction(content.property)}
{myFunction({prop:value, prop2: value2})}
coucou
coucou
) ``` Que des expressions [À vous](https://react.dev/learn/javascript-in-jsx-with-curly-braces#challenges) --- ## Propriétés - Comme les attributs du DOM - Se sont les « arguments » de la fonction composant ```js
// Ou
// ... function MyComponent(props) {...} // ou mieux function MyComponent({prop1, prop2}) {...} ``` C'est du JS classique. --- ## Utiliser le contenu du composant Example: ```js function Card({children}){ return
{children}
} function App(){ return (
Du jsx pépère
) } ``` [À vous](https://react.dev/learn/passing-props-to-a-component#challenges) --- ## Rendu conditionnel - Utilisation du JS classique - `if` + `return` - Opérateur ternaire, - `&&` ou `||` - Utilisation d'une variable [À vous](https://react.dev/learn/conditional-rendering#challenges) --- ## Rendre des listes - Utilisation du JS classique - `Array.map` - Unique `key` prop ? [À vous](https://react.dev/learn/rendering-lists#challenges) --- ## Construire son UI - Un arbre de composants - Découpage quand : - Réutilisation (potentielle ?) - Trop gros - Separation of concerns --- ## CSS ? - Attribut `style` - [CSS modules](https://vitejs.dev/guide/features.html#css) - `className` + utility classes - CSS-in-JS --- ## Bonnes pratiques - [Composants purs](https://react.dev/learn/keeping-components-pure) - Strict mode - Pas de manipulation de DOM - Separation of concerns --- ## Nouveau projet Avec [create-react-app](https://create-react-app.dev/) : ```sh npx create-react-app my-app ``` --- ## Avec vitejs Avec [Vitejs](https://vitejs.dev/) : - Node (nvm?) - `npm init vite@latest` - Sélectionnez `react` - puis la variante qui vous convient - ... --- ## Pratique Construire une application de Chat # Interactivité --- ## Réagir aux événements Événements DOM : click, change, submit, ... ```js
console.log('click')} /> // ou const onClick = (event) => { alert('À malibu'); } // ...
``` Pas `
` --- ## Utiliser l'événement - Argument du handler - Similaire à l'event original - `e.stopPropagation()` - `e.preventDefault()` [À vous](https://react.dev/learn/responding-to-events#challenges) --- ## Mémoire d'un composant hook `useState` ```js import { useState } from 'react'; const [index, setIndex] = useState(0); ``` On donne la valeur initiale, retourne la valeur courante et un « setter » --- ## Les hooks - Fonctions de React - Commencent par `use...` - Uniquement dans les composants... - ...et les autres hooks - Un hook ne doit pas être conditionnel --- ## Donc le useState - Stocke une variable pour un composant - Chaque composant a sa propre valeur [À vous](https://react.dev/learn/state-a-components-memory#challenges) --- ## Render - Rendre un composant : - C'est appeler sa function - Puis mettre à jour le DOM - C'est un processus récursif - Il se déclenche quand : - L'app se lance - Le state d'un composant change --- ## Commit - Pour le premier rendu : - Tout le DOM généré est ajouté au HTML - Après : - Mise à jour de ce qui a changé - Virtual DOM --- ## Donc le useState 2 - Utiliser le *setter* déclenche un *render* - **Seul** moyen de mettre à jour l'interface Lors du rendu du composant la valeur de chaque state est « récupérée ». Il est stocké « dans React ». --- ## Le setter 1 - Sont appelés lors d'un événement ou d'un effet - Les appels au setter sont accumulés... - ...et sont tous exécutés [après l'événement](https://react.dev/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) - Ils ne **modifient pas** la valeur courante [À vous](https://react.dev/learn/state-as-a-snapshot#challenges) --- ## Le setter 2 - Il est possible de modifier la valeur précédente - `setValue((prevValue)=> prevValue + 1)` [À vous](https://react.dev/learn/queueing-a-series-of-state-updates#challenges) --- ## Le setter 3 - Considérez les Objects et Array comme immutables - `{...prevValue}` ou `[...prevValue]` - Sinon pas de rendu et comportements incohérents - **NE JAMAIS-JAMAIS-JAMAIS LE FAIRE** ! - Attention aux sous objets À vous : - [Objects](https://react.dev/learn/updating-objects-in-state#challenges) - [Arrays](https://react.dev/learn/updating-arrays-in-state#challenges) --- # Aller plus loin - [Managing states](https://react.dev/learn/managing-state) # Les portes de sortie --- ## Les quoi ? - On peut déjà faire pas mal de choses... - ...mais on ne sait pas encore gérer tout ce qui est externe à React - `useRef` - `useEffect` --- ## useRef - Pour enregistrer des valeurs sans provoquer de render - Accéder au DOM - Utiliser des libs externes - Utiliser des APIs du navigateur - Ne pas l'utiliser pendant le render --- ## useRef 2 ```js import { useRef } from 'react'; // puis dans le composant const ref = useRef(0); // Pour l'utiliser ref.current = 10; ``` [À vous](https://react.dev/learn/referencing-values-with-refs#challenges) --- ## Accéder au DOM ```js const myRef = useRef(null); // ...
// ... const rect = myRef.current.boundingClientRect() ``` [À vous](https://react.dev/learn/manipulating-the-dom-with-refs#challenges) --- ## Synchronisation externe - Quand on veut synchroniser un state avec un element DOM - Utiliser une API non React (navigateur, autre lib, ...) - Communication avec un service externe (API, DB, Analytics, ...) --- ## useEffect Avec `useEffect()` : ```js import { useEffect } from 'react'; // Dans le composant useEffect(() => { // Code here will run after *every* render }); ``` --- ## Synchronisation conditionnelle Ajout de la liste de dépendances : ```js useEffect(() => { // Runned only if dependencies values have changed }, [liste, dependency]); ``` --- ## Synchronisation et nettoyage Parfois on veut nettoyer quelque chose : ```js useEffect(() => { // Effect code const connection = createDBConnection(username, password); connection.connect() return () => { //Cleanup code connection.close() } }, [username, password]); ``` --- ## Annuler une synchronisation ```js useEffect(async () => { const ignore = false const data = await fetchData(); if (!ignore){ setData(data) } return () => { ignore = true } }, []); ``` --- ## Attention - Le Strict Mode rend les composants deux fois - Tout [n'est pas un effet](https://react.dev/learn/you-might-not-need-an-effect) [À vous](https://react.dev/learn/synchronizing-with-effects#challenges) --- ## Pratique 2 Rendre interactive l'application de Chat # Context --- - Pour éviter le prop drilling - Pour séparer la logique des données et le rendu - Un peu comme des variables globales --- ## useContext - Permet de rendre disponible des variables à toute une sous arborescence. - Sans passer par le props --- ## useContext - Création ```js // Create context export const LevelContext = createContext(1); ``` --- ## useContext - Fournir ```js // Provide context
{children}
``` --- ## useContext - Utiliser ```js // Use context const level = useContext(LevelContext); ``` [À vous](https://react.dev/learn/passing-data-deeply-with-context#challenges) # Optimisation --- ## It's not a bug it's a feature - Éviter de refaire des calculs coûteux - Prévenir le rendu de certaines parties de l'arbre --- ## useMemo - Permet de mémoïzer quelque chose - En fonction d'une liste de dépendance - Pas de side effect ! ```js const memoized = useMemo(fn, deps) ``` [La doc](https://react.dev/reference/react/useMemo) --- ## memo - Pour mémoïzer un composant - Se rend seulement si une prop a changée - Attention aux fonctions ```js const MemoizedComponent = memo(SomeComponent, arePropsEqual?) ``` [La doc](https://react.dev/reference/react/memo) --- ## useCallback - Comme `useMemo` mais pour les fonctions ```js const cachedFn = useCallback(fn, dependencies) ``` [La doc](https://react.dev/reference/react/useCallback) # Déploiement --- ## Déployer un projet React ```sh $ npm run build # Et tout est dans le dist/ ``` # L'écosystème --- ## On y revient [Awesome react](https://github.com/enaqx/awesome-react) --- ## Pour le dev - [React developer tools](https://react.dev/learn/react-developer-tools) - [ESLint](https://github.com/jsx-eslint/eslint-plugin-react) --- ## Les frameworks - [Nextjs](https://nextjs.org/) - [Remix](https://remix.run/) --- ## Des composants - [Material-ui](https://mui.com/core/) --- ## Les routers - [React router](https://reactrouter.com/en/main) - [Wouter](https://github.com/molefrog/wouter) --- ## Les stores - [Redux](https://redux.js.org/) - [MobX](https://mobx.js.org/README.html) - [Zustand](https://zustand-demo.pmnd.rs/) --- ## Styling - [styled-components](https://styled-components.com/) - [Emotion](https://emotion.sh) --- ## Les formulaires - [React-hook-form](https://react-hook-form.com/) - [Formik](https://formik.org/) --- ## Faire des requêtes - [SWR](https://swr.vercel.app/fr-FR) - [TansSTack](https://tanstack.com/query/latest) --- ## Des hooks - [Hookz](https://react-hookz.github.io/web/) --- ## Testing - [Jest](https://jestjs.io/) - [Vitest](https://vitest.dev/) - [React testing library](https://testing-library.com/docs/react-testing-library/intro/) --- ## I18n - [FormatJS](https://formatjs.io/) - [React I18next](https://react.i18next.com/) --- ## React native - [React native](https://reactnative.dev/) - [Expo](https://expo.dev/) --- # À vous... --- # Des questions?