React JS
Packages
- Package
react
("platform-agnostic") - Puis des packages différents par plateforme. Chaque plateforme a ses propres primitives / éléments
react-dom
(web ; primitives = éléments html)react-native
(mobile ; pas de div mais des primitivesText
,View
,Pressable
,...)react-three-fiber
(scènes 3d ; primitives basées sur des formes et des textures)
Fonctionnement interne de React
- (Si utilisation de JSX, le JSX est compilé en JS et convertit en utilisant
createElement
ci-dessous) - Création d'un élément React :
React.createElement('p', {maProp: 'hello', 'Mon contenu ajouté en enfant'}
- Element React = un objet js avec différentes propriétés (type, key, ref, props,
_owner
,_store
) - Choix de la racine de l'app :
root = createRoot(monElementHTML)
- Puis on rend l'app :
root.render(reactElement)
(fonction render = convertit un élément react en node HTML)
JSX
- Depuis React 17, l'outil qui compile jsx en js importe aussi
React
(avant ce n'était pas le cas donc on pouvait se retrouver avecReact is not defined
qui pouvait être confus vu que React n'est pas utilisé directement en jsx) - Etant donné que le JSX est transformé en js, on ne peut pas utiliser de mots réservés en js, dans notre jsx
- Exemple : l'utilisation de
for
etclass
qui sont des mots réservés - Pour éviter cela, React utilise des variations :
htmlFor
,className
- Exemple : l'utilisation de
- Contrairement à l'HTML :
- tous les tags doivent être explicitement fermés, exemple : on ne peut pas faire
<img src="">
- les tags sont sensible à la casse (techniquement cet html est valide
<HEADER>
, mais en jsx ce n'est pas le cas) - Les attributs doivent être en camelCase (exemple:
tabIndex
) SAUF les attributsdata-
etaria-
qui gardent bien leurs tirets - l'attribut
style
ne prend pas une string mais un objet avec les propriétés en camelCasestyle={{fontSize: '2rem'}}
- tous les tags doivent être explicitement fermés, exemple : on ne peut pas faire
Cheat sheet
- Evenements
- en camelCase, on passe une fonction et pas une string
- Exemple :
onClick={activateLasers}
- Pour passer des args, fonction wrapper :
onClick={() => activateLasers(myParam)}
- Les événements personnalisés sont des
props
ajoutés au composant (la fonction est passée en param en callback)
- State : variables/état interne au composant sous forme de class.(
this.state
)- Initialisation du state dans le constructeur
- Pour ajouter des variables qui sont pas utilisée dans l'ui, je peux les ajouter directement sur l'instance de la classe (exemple
this.timerId
) - MAJ le state :
this.setState({})
(on ne modifie pas le state directement !!). Les MAJ sont mergées donc on peut setter juste la propriété qui nous intéresse. - les setters de state ne sont pas immédiats, mais asynchrones. Donc le setState agit sur le prochain rendu !! Si on a une fonction
onClick
qui contient de la logique après le setState, cela se fera sur la précédente valeur du state si on utilise le state. - Attention les changements doivent être immutable, si on modifie le state on doit fournir un nouvel array et pas muter un array existant
- La seule manière de passer le state à l'intérieur d'une app est d'utiliser les props
- Render
- Chaque re-render commence par un changement dans le state => ne re-render pas toute l'application, juste le composant et tous ses descendants
Hooks
- Fonctions React qui commencent par
use
. Peuvent être uniquement appelés dans un composant React et ne peuvent pas être appelés conditionnellement (car sinon l'ordre des appels de fonctions peut être changé). useState
=>const [maVar, setMaVar] = useState(maValeurParDefaut)
- useState peut aussi prendre une fonction en param
useId
: permet de créer un id unique sur l'instance du composant, qui va s'incrémenter avec le nb d'instance. Permet d'avoir toujours avoir un id unique sur la page (même valeur entre rendu client et serveur)useEffect
: se lance après le render d'un composant, permet de récupérer des informations après render. En "Strict Mode", UseEffect se lance deux fois après le premier mounted. (car en strict mode on vient lancer plusieurs fois certains bouts de code)useRef
: même fonctionnement de ref que VueJS (référence d'un élément du DOM). Utilisation :const canvasRef = React.useRef();
et<div ref={canvasRef}></div>
Optimisation de React
De manière générale, si les MAJ du state sont lentes, vérifier que :
- je suis sur un build de prod (car les build dev sont intentionnellement plus lents)
- Vérifier que je n'ai pas mis le state plus haut dans l'arbre que nécessaire
- Lancer le
React DevTools Profiler
pour voir ce qui est re-rendu, et wrapper les arbres les plus "chers" avecmemo()
(utiliseruseMemo()
là où il y a besoin)
Sources
- Before You memo() : amélioration de la performance sans utiliser
memo