Cours 10 - Synchro state et db
Manipulation du state - cas de figure
Section intitulée « Manipulation du state - cas de figure »La modification du state implique le respect de règles concernant l’immutabilité de celui-ci.
L’immutabilité fait référence à la propriété d’un objet qui ne peut pas être modifié. Une fois qu’un objet immuable est créé, son état reste constant tout au long de sa durée de vie. L’immutabilité offre plusieurs avantages, notamment la simplicité, la fiabilité et une meilleure concurrence. Elle permet une programmation plus sûre et plus prévisible, car les objets ne peuvent pas être modifiés accidentellement, ce qui réduit le nombre de bugs liés à des changements d’état inattendus.
Modification du state lorsqu’il s’agit d’un tableau - AJOUT
Section intitulée « Modification du state lorsqu’il s’agit d’un tableau - AJOUT »Les méthodes utilisées pour modifier le state lorsqu’il contient une référence (tableau ou objet) doivent se faire de façon immuable. C’est à dire qu’on ne doit pas modifier direct le tableau ou l’objet, mais le remplacer par un nouveau tableau ou un nouvel objet.
Pour ajouter un élément à un tableau, on utilisera donc la décomposition.
import {useState} from 'react';
const App = props => {
const [tableau, setTableau] = useState(['du texte', 'un autre texte']);
const ajouterAuTableau = () => { const textePourAjout = 'un nouveau texte'; setTableau((prevTableau) => [...prevTableau, textePourAjout]); };
{/* ... reste de la composante */}
};Modification du state lorsqu’il s’agit d’un tableau - SUPPRESSION
Section intitulée « Modification du state lorsqu’il s’agit d’un tableau - SUPPRESSION »Les méthodes utilisées pour modifier le state lorsqu’il contient une référence (tableau ou objet) doivent se faire de façon immuable. C’est à dire qu’on ne doit pas modifier direct le tableau ou l’objet, mais le remplacer par un nouveau tableau ou un nouvel objet.
Pour supprimer un élément d’un tableau, on pourra utiliser la méthode filter qui permet de conserver uniquement les éléments respectant une condition donnée.
import {useState} from 'react';
const App = props => {
const [tableau, setTableau] = useState(['Adam','Julie','Nicolas','Rocktavie','Lucienne','Louiselle']);
const supprimerDuTableau = () => { //supprime l'élément à la position 0 du tableau setTableau(prevTableau => prevTableau.filter((texte, i) => { // conserve tous les éléments qui ne sont pas situés à la première position du tableau return i !== 0; })); };
{/* ... reste de la composante */}
};Modification du state lorsqu’il s’agit d’un tableau - MODIFICATION
Section intitulée « Modification du state lorsqu’il s’agit d’un tableau - MODIFICATION »Les méthodes utilisées pour modifier le state lorsqu’il contient une référence (tableau ou objet) doivent se faire de façon immuable. C’est à dire qu’on ne doit pas modifier direct le tableau ou l’objet, mais le remplacer par un nouveau tableau ou un nouvel objet.
Pour modifier un élément d’un tableau, on pourra utiliser la méthode map qui permet de conserver le même nombre d’élément, mais de pouvoir les transformer/modifier.
import {useState} from 'react';
const App = props => {
const [tableau, setTableau] = useState(['Adam','Julie','Nicolas','Rocktavie','Lucienne','Louiselle']);
const modificationDuTableau = () => { //met l'élément 0 du tableau en lettre majuscule setTableau(prevTableau => prevTableau.map((texte, i) => { // conserve tous les éléments intacts sauf le premier return i === 0 ? texte.toUpperCase() : texte; })); };
{/* ... reste de la composante */}
};Modification du state lorsqu’il s’agit d’un objet
Section intitulée « Modification du state lorsqu’il s’agit d’un objet »Les méthodes utilisées pour modifier le state lorsqu’il contient une référence (tableau ou objet) doivent se faire de façon immuable. C’est à dire qu’on ne doit pas modifier direct le tableau ou l’objet, mais le remplacer par un nouveau tableau ou un nouvel objet.
Pour modifier un élément d’un tableau, on pourra utiliser la méthode [map] qui permet de conserver le même nombre d’élément, mais de pouvoir les transformer/modifier.
import {useState} from 'react';
const App = props => {
const [infos, setInfos] = useState({ prenom: 'Robert-Denis', nom: 'Rheault, age: 66 });
const modifierAge = (nouvelAge) => { setInfos(current => { return { ...current, // on copie l'objet d'origine par décomposition age: nouvelAge // on écrase ensuite la propriété voulue }; }); };
{/* ... reste de la composante */}
};Modification d’un élément à l’intérieur d’un tableau d’objets
Section intitulée « Modification d’un élément à l’intérieur d’un tableau d’objets »La tâche se complexifie quelque peu puisqu’il est nécessaire de modifier à la fois un tableau et un objet selon les méthodes prescrites. On utilisera donc un .map pour permettre de modifier un élément du tableau (en utilisant un identifiant quelconque pour reconnaître le bon objet à modifier) et on modifiera l’objet selon la méthode recommandée ci-dessus.
import {useState} from 'react';
const App = props => {
const [tableau, setTableau] = useState([ { id: 'a' prenom: 'Robert-Denis', nom: 'Rheault', age: 66 }, { id: 'b' prenom: 'Bill', nom: 'Paxton', age: 52 } ]);
const modifierAge = (actorId, nouvelAge) => { setTableau(current => current.map((acteur) => { // si l'acteur ne correspond pas à celui à modifier, on le garde tel quel // si c'est le même on modifie l'objet par décomposition et on le retourne au map return acteur.id !== actorId ? acteur : { ...acteur, age: nouvelAge }; })); };
{/* ... reste de la composante */}
}onSubmit
Section intitulée « onSubmit »Plutôt que d’utiliser une action (qui reçoit un formData) sur un formulaire, il peut être parfois utile de court-circuiter cet envoi si on désire travailler davantage avec les states au premier plan. On utilisera alors l’attribut onSubmit du formulaire.
Plutôt que de recevoir un formData, onSubmit est un écouteur d’événement recevant l’événement lui-même en paramètre. On devra alors recréer un formData à partir de la référence au formulaire.
const MaComposante = () => { const submitHandler = (e) => { // empêche le formulaire d'être soumis et la page de se recharger e.preventDefault();
// recrée le formData à partir du formulaire (e.target) const formData = new FormData(e.target);
// manipulations du state & appel potentiel d'une action serveur
// réinitialise le formulaire e.reset(); };
return ( <div> <form onSubmit={submitHandler}> <label for="fld_name">Nom:</label> <input id="fld_name" type="text" name="name"/> <button>Soumettre</button> </form> </div> );}UploadThing
Section intitulée « UploadThing »Documentation Typescript pour Next.js
Utilisation de React-Flow (selon l’exemple fourni)
Section intitulée « Utilisation de React-Flow (selon l’exemple fourni) »Noeuds (nodes)
Section intitulée « Noeuds (nodes) »Composante représentant le bloc de construction de base du schéma. Son visuel sera différent en fonction de son type et il est également possible d’ajouter des types personnalisés.
- input: noeud de départ. Il possède un handle vers le bas
- output: noeud de fin. Il possède un handle vers le haut
- default: noeud commun. Il possède un handle vers le haut et un handle vers le bas.
Type personnalisé
Section intitulée « Type personnalisé »Documentation
N’importe quelle composante peut devenir un noeud. Il suffit de créer la composante et l’assigner à un nouveau type dans la propriété nodeTypes dans le fichier gridStore.js (ligne 12). Il est possible d’ajouter des Handles pour les connecter à d’autres noeuds.
Propriétés de base d’un node
Section intitulée « Propriétés de base d’un node »- id: string
- position:
{x: number, y: number} - type: (optionnel) ‘input’ | ‘output’ | ‘default’ (ou autre type custom déclaré dans
nodeTypes) - data: (optionnel) données arbitraires qui seront passées à la composante. Si une propriété label y existe, son texte sera affiché dans les noeuds de base. Pour conserver de la flexibilité dans la bd, cette propriété pourrait être sauvegardée dans un format json.
Branches
Section intitulée « Branches »Élément visuel connectant les noeuds ensemble. On les crée en cliquant sur une poignée (handle) et en relâchant sur la poignée d’un autre noeud.
- default: courbe de bézier
- straight: ligne droite
- step: courbe carrée🤔
- smoothstep: courbe carrée avec coins arrondis 😢
Propriétés de base d’une branche
Section intitulée « Propriétés de base d’une branche »- id: string
- source: id du noeud source
- target: id du noeud d’arrivée
- label: (optionnel): texte affiché sur la branche
- animated: (optionnel): booléen
- type: (optionnel) ‘default’ | ‘straight’ | ‘step’ | ‘smoothstep’
Fichiers notables
Section intitulée « Fichiers notables »_stores/gridStore.js
Section intitulée « _stores/gridStore.js »La logique y est centralisé. C’est là qu’on y gère les différentes states (nodes et edges). On y trouve certaines propriétés et fonctions pouvant être complétées. Il est également possible (et encouragé) d’en ajouter d’autres.
C’est aussi de ces fonctions que peuvent être appelées les actions serveur une fois les states modifiés.
Propriétés et méthodes utiles
Section intitulée « Propriétés et méthodes utiles »selection: Indique ce qui est sélectionné par l’utilisateur (node | edge | none) et leurs infos (fonctionne déjà, complet).addNode: Permet d’ajouter un noeud au schéma (à appeler et à complétér)updateNodePosition: Affiche présentement l’id et la position d’un noeud après son déplacement (s’appelle automatiquement déjà, à compléter)createEdge: Permet d’ajouter une branche au state (s’appelle automatiquement déjà, à compléter) Le reste est à ajouter en fonction de vos besoins
_hooks/useGridInternals.js
Section intitulée « _hooks/useGridInternals.js »On y trouve la mécanique interne de React-Flow. Il est normalement inutile et déconseillé de modifier ce fichier. Ce code a été séparé de gridStore.js afin de simplifier ce dernier.
_contexts/GridProvider.jsx
Section intitulée « _contexts/GridProvider.jsx »Il est utilisé afin d’injecter les données du serveur dans le gridStore.js par les props (à faire). La composante GridProvider est déjà utilisée dans le fichier page.jsx (à regarder).
_components/nodes/CustomNode.jsx
Section intitulée « _components/nodes/CustomNode.jsx »Un exemple d’un noeud personnalisé. Il reçoit plusiers props et utilise des poignées (Handles) pour permettre la connexion.
_components/ClientPage.jsx:
Section intitulée « _components/ClientPage.jsx: »On y trouve la composante <ReactFlow> permettant d’afficher le schéma. Celle-ci est déjà configurée et “branchée” au store.
On y trouve un exemple temporaire d’utilisation d’addNode.
