« Max reacjsex » : différence entre les versions

Aucun résumé des modifications
 
(18 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
Voici une '''architecture ReactJS''' basée sur vos composants déclaratifs, en mettant l’accent sur les '''points clés de réactivité'''. Je vais structurer l’application avec :<br />
Pour organiser l’arborescence des fichiers JSX et les imports dans une application React, il est important de structurer les fichiers de manière logique et modulaire. Voici une suggestion d’organisation sous forme de tableau, ainsi qu’une indication sur la manière de gérer les imports.
- Une hiérarchie de composants<br />
== '''1.Exemple''' ==
- La gestion d’état stratégique (local vs global)<br />
<span id="arborescence-des-fichiers-jsx"></span>
- Les dépendances réactives (conditions, effets)
=== Arborescence des fichiers JSX ===


{| class="wikitable"
|-
! Chemin du fichier
! Description
|-
| <code>/src/index.jsx</code>
| Point d’entrée principal de l’application.
|-
| <code>/src/App.jsx</code>
| Composant principal de l’application.
|-
| <code>/src/components/Application.jsx</code>
| Composant racine de l’application.
|-
| <code>/src/components/Page.jsx</code>
| Composant de la page principale.
|-
| <code>/src/components/FormAdresse.jsx</code>
| Composant du formulaire d’adresse.
|-
| <code>/src/components/Adresse.jsx</code>
| Composant d’adresse.
|-
| <code>/src/components/AttributAdresse.jsx</code>
| Composant pour les attributs de l’adresse.
|-
| <code>/src/components/Etage.jsx</code>
| Composant pour l’étage.
|-
| <code>/src/components/CodeAcces.jsx</code>
| Composant pour le code d’accès.
|-
| <code>/src/components/CodePos.jsx</code>
| Composant pour le code postal.
|-
| <code>/src/components/Ville.jsx</code>
| Composant pour la ville.
|-
| <code>/src/components/Zone.jsx</code>
| Composant pour la zone.
|-
| <code>/src/components/RueToureP.jsx</code>
| Composant pour la rue/tour/étage.
|-
| <code>/src/components/Tou.jsx</code>
| Composant pour le numéro de tour.
|-
| <code>/src/components/Rep.jsx</code>
| Composant pour le numéro de répétition.
|-
| <code>/src/components/Etablissement.jsx</code>
| Composant pour l’établissement.
|-
| <code>/src/components/Geoloc.jsx</code>
| Composant pour la géolocalisation.
|-
| <code>/src/components/CoordXY.jsx</code>
| Composant pour les coordonnées XY.
|-
| <code>/src/components/ZoneTexte.jsx</code>
| Composant pour les zones de texte.
|-
| <code>/src/components/ZoneNumerique.jsx</code>
| Composant pour les zones numériques.
|-
| <code>/src/components/Bouton.jsx</code>
| Composant pour les boutons.
|}


-----
<span id="gestion-des-imports"></span>
=== Gestion des imports ===


<span id="structure-de-fichiers-simplifiée"></span>
Pour les imports, chaque fichier JSX importera les composants et les dépendances nécessaires. Voici comment vous pourriez structurer les imports dans chaque fichier :
=== '''1. Structure de Fichiers (Simplifiée)''' ===


<syntaxhighlight lang="bash">src/
<span id="points-clés"></span>
├── components/
=== Points clés ===
│  ├── common/              # Composants réutilisables
│  │  ├── ZoneNumerique.jsx
│  │  ├── ZoneTexte.jsx
│  │  └── Bouton.jsx
│  ├── geoloc/              # Modules spécifiques
│  │  ├── Geoloc.jsx
│  │  └── CoordXY.jsx
│  └── formadresse/          # Formulaire d'adresse
│      ├── AttributAdresse.jsx
│      ├── CodePos.jsx
│      └── Ville.jsx
├── pages/
│  └── Application.jsx      # Point d'entrée
└── App.jsx                  # Racine React</syntaxhighlight>


-----
* '''Modularité''' : Chaque composant est dans son propre fichier, ce qui facilite la maintenance et la réutilisation.
* '''Imports relatifs''' : Utilisez des chemins relatifs pour importer des composants dans d’autres fichiers.
* '''Structure claire''' : Une arborescence bien définie aide à comprendre rapidement où se trouvent les différents composants.


<span id="squellette-de-lapplication"></span>
Cette structure vous permet de garder votre code bien organisé et facile à naviguer.
=== '''2. Squellette de l’Application''' ===


<span id="a.-composants-de-base-réutilisables"></span>
Pour ajouter la logique de chaque composant tout en respectant la condition selon laquelle la ville est affichée uniquement si un code postal est saisi, nous allons utiliser le hook <code>useState</code> pour gérer l’état local de chaque composant. Voici comment vous pourriez structurer chaque fichier avec sa logique respective :
==== '''A. Composants de Base (Réutilisables)''' ====


<syntaxhighlight lang="js" line copy>// components/common/ZoneNumerique.jsx
<span id="exemple-de-srccomponentszonetexte.jsx"></span>
export const ZoneNumerique = ({ value, onChange, disabled }) => {
===  <code>/src/components/ZoneTexte.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
 
const ZoneTexte = ({ value, onChange }) => {
  return <input type="text" value={value} onChange={onChange} />;
};
 
export default ZoneTexte;</syntaxhighlight>
<span id="exemple-de-srccomponentszonenumerique.jsx"></span>
===  <code>/src/components/ZoneNumerique.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
 
const ZoneNumerique = ({ value, onChange }) => {
  return <input type="number" value={value} onChange={onChange} />;
};
 
export default ZoneNumerique;</syntaxhighlight>
<span id="exemple-de-srccomponentsbouton.jsx"></span>
===  <code>/src/components/Bouton.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
 
const Bouton = ({ valeur, etat, onClick }) => {
   return (
   return (
     <input
     <button onClick={onClick} disabled={etat === 'désactivé'}>
      type="number"
       {valeur}
      value={value}  
     </button>
      onChange={(e) => onChange(e.target.value)}
       disabled={disabled}
     />
   );
   );
};
};
};</syntaxhighlight>
 
<syntaxhighlight lang="jsx" line copy>// components/common/Bouton.jsx
export default Bouton;</syntaxhighlight>
export const Bouton = ({ label, onClick, disabled }) => {
<span id="exemple-de-srccomponentscoordxy.jsx"></span>
===  <code>/src/components/CoordXY.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneTexte from './ZoneTexte';
 
const CoordXY = ({ x, y, onXChange, onYChange }) => {
  return (
    <div>
      <ZoneTexte value={x} onChange={onXChange} />
      <ZoneTexte value={y} onChange={onYChange} />
    </div>
  );
};
 
export default CoordXY;</syntaxhighlight>
<span id="exemple-de-srccomponentsgeoloc.jsx"></span>
===  <code>/src/components/Geoloc.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React, { useState } from 'react';
import CoordXY from './CoordXY';
 
const Geoloc = () => {
  const [x, setX] = useState('');
  const [y, setY] = useState('');
 
  const handleXChange = (e) => setX(e.target.value);
  const handleYChange = (e) => setY(e.target.value);
 
   return (
   return (
     <button onClick={onClick} disabled={disabled}>
     <div>
      {label}
      <CoordXY
     </button>
        x={x}
        y={y}
        onXChange={handleXChange}
        onYChange={handleYChange}
      />
     </div>
   );
   );
};
};
};</syntaxhighlight>


-----
export default Geoloc;</syntaxhighlight>
<span id="exemple-de-srccomponentsetage.jsx"></span>
===  <code>/src/components/Etage.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneTexte from './ZoneTexte';
 
const Etage = ({ value, onChange }) => {
  return <ZoneTexte value={value} onChange={onChange} />;
};
 
export default Etage;</syntaxhighlight>
<span id="exemple-de-srccomponentscodeacces.jsx"></span>
===  <code>/src/components/CodeAcces.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const CodeAcces = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default CodeAcces;</syntaxhighlight>
<span id="exemple-de-srccomponentscodepos.jsx"></span>
===  <code>/src/components/CodePos.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const CodePos = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default CodePos;</syntaxhighlight>
<span id="exemple-de-srccomponentsville.jsx"></span>
===  <code>/src/components/Ville.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneTexte from './ZoneTexte';
 
const Ville = ({ value, onChange }) => {
  return <ZoneTexte value={value} onChange={onChange} />;
};


<span id="b.-composants-contextuels-réactivité-conditionnelle"></span>
export default Ville;</syntaxhighlight>
==== '''B. Composants Contextuels (Réactivité Conditionnelle)''' ====
<span id="exemple-de-srccomponentsadresse.jsx"></span>
=== <code>/src/components/Adresse.jsx</code> ===


<syntaxhighlight lang="jsx" line copy>/ components/formadresse/Ville.jsx
<syntaxhighlight lang="jsx" line copy>import React, { useState } from 'react';
export const Ville = ({ codePostal }) => {
import Etage from './Etage';
  const [ville, setVille] = useState("");
import CodeAcces from './CodeAcces';
import CodePos from './CodePos';
import Ville from './Ville';
import Zone from './Zone';


  // Effet réactif : Chargement de la ville basé sur le code postal
const Adresse = () => {
  useEffect(() => {
  const [etage, setEtage] = useState('');
    if (codePostal) {
  const [codeAcces, setCodeAcces] = useState('');
      // Simule un appel API (ex: fetch(`/api/villes?cp=${codePostal}`))
  const [codePos, setCodePos] = useState('');
      setVille("Paris"); // Valeur mockée
   const [ville, setVille] = useState('');
    }
   }, [codePostal]); // Dépendance réactive


   return <ZoneTexte value={ville} onChange={setVille} />;
   return (
    <div>
      <Etage value={etage} onChange={(e) => setEtage(e.target.value)} />
      <CodeAcces value={codeAcces} onChange={(e) => setCodeAcces(e.target.value)} />
      <CodePos value={codePos} onChange={(e) => setCodePos(e.target.value)} />
      {codePos && <Ville value={ville} onChange={(e) => setVille(e.target.value)} />}
      <Zone />
    </div>
  );
};
};
};</syntaxhighlight>


-----
export default Adresse;</syntaxhighlight>
==== Explication ====
 
* '''Condition <code>{codePos &amp;&amp; <Ville ... />}</code>''' : Cette ligne signifie que le composant <code>Ville</code> ne sera rendu que si <code>codePos</code> a une valeur non vide. Si <code>codePos</code> est une chaîne vide (<code>''</code>), alors le composant <code>Ville</code> ne sera pas affiché.
* '''Gestion de l’État''' : Lorsque l’utilisateur saisit quelque chose dans le champ <code>CodePos</code>, l’état <code>codePos</code> est mis à jour, ce qui déclenche un re-rendu du composant <code>Adresse</code>. Si <code>codePos</code> a une valeur, le composant <code>Ville</code> est alors affiché.
 
Cette approche permet de s’assurer que le champ de la ville n’est visible que lorsque l’utilisateur a saisi un code postal, ce qui peut être utile pour des raisons de logique métier ou d’expérience utilisateur.
 


<span id="c.-gestion-détat-global-contexte-ou-redux"></span>
<span id="exemple-de-srccomponentszone.jsx"></span>
==== '''C. Gestion d’État Global (Contexte ou Redux)''' ====


<syntaxhighlight lang="jsx" line copy>// contexts/AdresseContext.jsx
===  <code>/src/components/Zone.jsx</code> ===
import { createContext, useState } from 'react';


export const AdresseContext = createContext();
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import RueToureP from './RueToureP';
import Tou from './Tou';
import Rep from './Rep';
import Etablissement from './Etablissement';
import Geoloc from './Geoloc';


export const AdresseProvider = ({ children }) => {
const Zone = () => {
   const [adresse, setAdresse] = useState({
   const [rueToureP, setRueToureP] = React.useState('');
    codePostal: "",
  const [tou, setTou] = React.useState('');
    ville: "",
  const [rep, setRep] = React.useState('');
    etage: "",
  const [etablissement, setEtablissement] = React.useState('');
    // ... autres champs
  });


   return (
   return (
     <AdresseContext.Provider value={{ adresse, setAdresse }}>
     <div>
       {children}
      <RueToureP value={rueToureP} onChange={(e) => setRueToureP(e.target.value)} />
     </AdresseContext.Provider>
      <Tou value={tou} onChange={(e) => setTou(e.target.value)} />
      <Rep value={rep} onChange={(e) => setRep(e.target.value)} />
       <Etablissement value={etablissement} onChange={(e) => setEtablissement(e.target.value)} />
      <Geoloc />
     </div>
   );
   );
};
};
};</syntaxhighlight>


-----
export default Zone;</syntaxhighlight>
<span id="exemple-de-srccomponentsruetourep.jsx"></span>
===  <code>/src/components/RueToureP.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const RueToureP = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default RueToureP;</syntaxhighlight>
<span id="exemple-de-srccomponentstou.jsx"></span>
===  <code>/src/components/Tou.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const Tou = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default Tou;</syntaxhighlight>
<span id="exemple-de-srccomponentsrep.jsx"></span>
===  <code>/src/components/Rep.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const Rep = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default Rep;</syntaxhighlight>
<span id="exemple-de-srccomponentsetablissement.jsx"></span>
===  <code>/src/components/Etablissement.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ZoneNumerique from './ZoneNumerique';
 
const Etablissement = ({ value, onChange }) => {
  return <ZoneNumerique value={value} onChange={onChange} />;
};
 
export default Etablissement;</syntaxhighlight>
<span id="exemple-de-srccomponentsformadresse.jsx"></span>
===  <code>/src/components/FormAdresse.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import Adresse from './Adresse';


<span id="d.-composant-principal-application"></span>
const FormAdresse = () => {
==== '''D. Composant Principal (<code>Application</code>)''' ====
  return (
    <div>
      <Adresse />
    </div>
  );
};


<syntaxhighlight lang="jsx" line copy>// pages/Application.jsx
export default FormAdresse;</syntaxhighlight>
import { AdresseProvider } from '../contexts/AdresseContext';
<span id="exemple-de-srccomponentspage.jsx"></span>
import { FormAdresse } from '../components/formadresse/FormAdresse';
===  <code>/src/components/Page.jsx</code> ===
import { Bouton } from '../components/common/Bouton';


export const Application = () => {
<syntaxhighlight lang="jsx" line copy>import React from 'react';
  const [isFormValid, setIsFormValid] = useState(false);
import FormAdresse from './FormAdresse';
import Bouton from './Bouton';


  // Logique de validation réactive (ex: vérifie si tous les champs sont remplis)
const Page = () => {
   useEffect(() => {
   const handleSave = () => {
     // Implémentez la validation ici
     // Logique pour enregistrer les données
     setIsFormValid(true); // Mock
     console.log('Enregistrement des données');
   }, []); // Dépendances à ajuster
   };


   return (
   return (
     <AdresseProvider>
     <div>
       <FormAdresse />
       <FormAdresse />
       <Bouton  
       <Bouton valeur="Enregistrer" etat="activer" onClick={handleSave} />
        label="Enregistrer"  
    </div>
        disabled={!isFormValid} // Désactivé si le formulaire est invalide
  );
        onClick={() => console.log("Sauvegarde...")}
};
       />
 
     </AdresseProvider>
export default Page;</syntaxhighlight>
<span id="exemple-de-srccomponentsapplication.jsx"></span>
===  <code>/src/components/Application.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import Page from './Page';
 
const Application = () => {
  return (
    <div>
      <Page />
    </div>
  );
};
 
export default Application;</syntaxhighlight>
<span id="exemple-de-srcapp.jsx"></span>
===  <code>/src/App.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import Application from './components/Application';
 
const App = () => {
  return (
    <div className="App">
       <Application />
     </div>
   );
   );
};
};
};</syntaxhighlight>


-----
export default App;</syntaxhighlight>
<span id="exemple-de-srcindex.jsx"></span>
===  <code>/src/index.jsx</code> ===
 
<syntaxhighlight lang="jsx" line copy>import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
 
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);</syntaxhighlight>
Cette structure vous permet de gérer l’état local de chaque composant et de conditionner l’affichage de la ville en fonction de la saisie du code postal. Chaque composant est responsable de sa propre logique et de son rendu, ce qui facilite la maintenance et l’évolution de l’application.
 
== '''2.Exemple Ville from CodPos''' ==
 
Pour créer un composant <code>Ville</code> qui affiche une liste de villes provenant d’une API fictive et qui se base sur le <code>codePos</code> pour sélectionner la bonne ville, nous allons suivre les étapes suivantes :
 
# '''Simuler une API''' : Nous allons simuler une API qui renvoie une liste de villes en fonction du <code>codePos</code>.
# '''Composant <code>Ville</code>''' : Ce composant va récupérer les villes en fonction du <code>codePos</code> et afficher une liste déroulante (<code>select</code>) des villes correspondantes.
# '''Mécanisme de Sélection''' : Lorsque le <code>codePos</code> change, le composant <code>Ville</code> va mettre à jour la liste des villes.
 
Voici comment vous pourriez structurer cela :


<span id="points-stratégiques-de-réactivité"></span>
<span id="simulation-de-lapi"></span>
=== '''3. Points Stratégiques de Réactivité''' ===


# '''État Local vs Global'''
=== Simulation de l’API ===
#* <code>ZoneNumerique</code>/<code>ZoneTexte</code> : État local si isolé.<br />


#* <code>Ville</code> : Dépend d’un état parent (<code>codePostal</code>) → '''Effet réactif'''.<br />
Nous allons créer une fonction qui simule un appel API pour récupérer les villes en fonction du <code>codePos</code>.


#* <code>Bouton</code> : Désactivé conditionnellement (<code>isFormValid</code>).
<syntaxhighlight lang="jsx" line copy>// Simuler un appel API
# '''Effets de Bord'''
const fetchVillesByCodePos = async (codePos) => {
#* Chargement de la ville après un changement de code postal (<code>useEffect</code>).
  // Simuler des données fictives
# '''Optimisation'''
  const villesData = {
#* Mémoisation des composants (<code>React.memo</code>) si re-rendus fréquents.<br />
    '75001': ['Paris 1'],
    '75002': ['Paris 2'],
    '69001': ['Lyon 1'],
    '69002': ['Lyon 2'],
    // Ajoutez d'autres codes postaux et villes fictives ici
  };


#* Éviter les props inutiles qui déclenchent des re-rendus.
  // Simuler un délai de réponse de l'API
# '''Validation Réactive'''
  return new Promise((resolve) => {
#* Un custom hook comme <code>useFormValidation</code> pourrait surveiller les changements de l’état global.
    setTimeout(() => {
      resolve(villesData[codePos] || []);
    }, 500);
  });
};</syntaxhighlight>
<span id="composant-ville"></span>
=== Composant <code>Ville</code> ===


Le composant <code>Ville</code> va utiliser le hook <code>useEffect</code> pour appeler la fonction <code>fetchVillesByCodePos</code> chaque fois que le <code>codePos</code> change.


-----
<syntaxhighlight lang="jsx" line copy>import React, { useState, useEffect } from 'react';


<span id="exemple-de-flux-réactif"></span>
const Ville = ({ codePos }) => {
=== '''4. Exemple de Flux Réactif''' ===
  const [villes, setVilles] = useState([]);
  const [selectedVille, setSelectedVille] = useState('');


* L’utilisateur remplit <code>CodePos</code> '''déclenche''' un effet dans <code>Ville</code>.<br />
  useEffect(() => {
    const fetchVilles = async () => {
      if (codePos) {
        const villes = await fetchVillesByCodePos(codePos);
        setVilles(villes);
        setSelectedVille(villes[0] || '');
      }
    };


* La modification de <code>ville</code> met à jour l’état global → '''notifie''' le bouton “Enregistrer”.<br />
    fetchVilles();
  }, [codePos]);


* Si tous les champs sont valides, le bouton passe en <code>disabled={false}</code>.
  const handleVilleChange = (e) => {
    setSelectedVille(e.target.value);
  };


  return (
    <div>
      {villes.length > 0 ? (
        <select value={selectedVille} onChange={handleVilleChange}>
          {villes.map((ville, index) => (
            <option key={index} value={ville}>
              {ville}
            </option>
          ))}
        </select>
      ) : (
        <p>Aucune ville trouvée pour ce code postal.</p>
      )}
    </div>
  );
};


-----
export default Ville;</syntaxhighlight>
<span id="intégration-dans-le-composant-adresse"></span>
=== Intégration dans le Composant <code>Adresse</code> ===


<span id="pour-aller-plus-loin"></span>
Enfin, nous allons intégrer le composant <code>Ville</code> dans le composant <code>Adresse</code> et passer le <code>codePos</code> comme prop.
=== '''5. Pour Aller Plus Loin''' ===


* '''Librairies utiles''' :
<syntaxhighlight lang="jsx" line copy>import React, { useState } from 'react';
** <code>react-hook-form</code> pour la gestion de formulaires complexes.<br />
import Etage from './Etage';
import CodeAcces from './CodeAcces';
import CodePos from './CodePos';
import Ville from './Ville';
import Zone from './Zone';


** <code>react-query</code> pour les appels API réactifs.<br />
const Adresse = () => {
  const [etage, setEtage] = useState('');
  const [codeAcces, setCodeAcces] = useState('');
  const [codePos, setCodePos] = useState('');


* '''Tests''' : Vérifiez les performances avec <code>React DevTools Profiler</code>.
  return (
    <div>
      <Etage value={etage} onChange={(e) => setEtage(e.target.value)} />
      <CodeAcces value={codeAcces} onChange={(e) => setCodeAcces(e.target.value)} />
      <CodePos value={codePos} onChange={(e) => setCodePos(e.target.value)} />
      {codePos && <Ville codePos={codePos} />}
      <Zone />
    </div>
  );
};


export default Adresse;</syntaxhighlight>
<span id="explication"></span>
=== Explication ===


-----
* '''Appel API Simulé''' : La fonction <code>fetchVillesByCodePos</code> simule un appel API et renvoie une liste de villes en fonction du <code>codePos</code>.
* '''Hook <code>useEffect</code>''' : Le composant <code>Ville</code> utilise <code>useEffect</code> pour appeler la fonction <code>fetchVillesByCodePos</code> chaque fois que le <code>codePos</code> change.
* '''Liste Déroulante''' : Le composant <code>Ville</code> affiche une liste déroulante (<code>select</code>) des villes correspondantes au <code>codePos</code>. Si aucune ville n’est trouvée, un message est affiché.


Cette architecture sépare clairement :<br />
Cette approche permet de sélectionner dynamiquement les villes en fonction du code postal saisi par l’utilisateur.
- Les '''composants UI''' (stateless si possible).<br />
- La '''logique réactive''' (effets, état).<br />
- Les '''règles métier''' (validation, dépendances).


😊


== Vidéos ==
[https://www.youtube.com/watch?v=1p6TsZW_HDk C'est quoi react (Youtube)]


[[Category:Private]]
[[Category:React]]