Dans de nombreuses applications web, nous rencontrons souvent des formulaires où sélectionner une option dans une liste déroulante débloque un nouvel ensemble d’options dans une autre. Ces listes déroulantes interconnectées, communément appelées listes déroulantes dépendantes ou en cascade, jouent un rôle crucial dans la création d’une expérience de remplissage de formulaire fluide et intuitive.
Que ce soit en sélectionnant un pays pour révéler les états correspondants ou en choisissant une catégorie de produit pour afficher des articles spécifiques, ces listes déroulantes simplifient les choix complexes pour tout le monde. Pour les développeurs, la mise en œuvre de listes déroulantes dépendantes est un défi pratique qui combine logique, facilité d’utilisation et gestion dynamique des données.
Dans ce tutoriel, vous apprendrez comment implémenter ce type de liste déroulante dans votre application React.
Table des matières
Qu’est-ce qu’un menu déroulant dépendant ?
Un menu déroulant dépendant est un élément d’interface utilisateur dans lequel les options disponibles dans un menu déroulant sont déterminées par la sélection effectuée dans un autre menu déroulant. Par exemple, considérons un scénario où vous avez deux menus déroulants :
-
Menu déroulant des pays : L’utilisateur sélectionne un pays.
-
Menu déroulant des villes : En fonction du pays sélectionné, la liste des villes disponibles dans le deuxième menu déroulant sera filtrée en conséquence.
Ce type d’interaction est crucial pour les formulaires qui nécessitent des saisies de données complexes et sensibles au contexte.
Comment fonctionne un menu déroulant dépendant ?
Les menus déroulants dépendants fonctionnent en mettant à jour dynamiquement les options du deuxième menu déroulant en fonction de la valeur sélectionnée dans le premier menu déroulant. Ce changement dynamique est généralement réalisé par :
-
Écouter l’entrée de l’utilisateur : Lorsque l’utilisateur sélectionne une option dans le premier menu déroulant, un événement (généralement onChange) déclenche une fonction pour mettre à jour l’état.
-
Récupération de nouvelles données: Cet état mis à jour peut être utilisé pour filtrer les données existantes ou effectuer un appel API pour récupérer la nouvelle liste d’options.
-
Rendering de nouvelles données: Le deuxième menu déroulant est ensuite mis à jour avec les nouvelles options, offrant à l’utilisateur des choix pertinents.
Étapes pour créer des menus déroulants dépendants en React
Étape 1: Configurer votre projet React
Si vous débutez avec React et que vous souhaitez suivre, consultez la documentation de Vite et suivez les étapes pour créer votre projet React. Une fois terminé, revenez ici et continuons à construire.
Si vous avez déjà un projet React que vous souhaitez utiliser, c’est aussi très bien.
Étape 2: Structurer le composant
Pour simplifier, supposons que nous construisons un menu déroulant dépendant à deux niveaux où le premier menu déroulant vous permet de choisir un pays, et le second menu déroulant affiche les villes en fonction du pays sélectionné.
De plus, dans le menu déroulant des pays, nous aurons une autre option pour entrer un nom de pays qui n’est pas inclus dans les options de pays. L’utilisateur pourra ensuite entrer son pays dans un champ de texte.
Tout d’abord, créez un nouveau fichier nommé DependentDropdown.js
ou DependentDropdown.jsx
. Dans ce fichier, définissez un composant fonctionnel appelé DependentDropdown
.
Nous allons maintenant suivre les étapes suivantes pour construire notre menu déroulant dépendant :
Déclarer des variables pour stocker des données
Nous devons créer des données statiques pour les valeurs de nos pays et villes :
// Données statiques des pays
const countries = [
{ id: 1, name: 'USA' },
{ id: 2, name: 'Canada' },
{ id: 3, name: 'Other' },
];
// Données statiques des villes correspondant aux pays
const cities = {
USA: ['New York', 'Los Angeles', 'Chicago'],
Canada: ['Toronto', 'Vancouver', 'Montreal'],
};
-
countries
est un tableau d’objets. Chaque objet ayant des propriétésid
etname
. -
cities
est un objet avec des noms de pays comme clés et les valeurs comme tableau de villes.
Déclarer des variables d’état
Pour chaque sélection de pays ou de villes, nous voulons pouvoir suivre les valeurs sélectionnées. Nous voulons également pouvoir remplir l’option des villes après qu’une sélection de pays a été faite. Pour ce faire, nous devons déclarer certains états.
Si le concept d’état est nouveau pour vous, vous pouvez lire mon article sur l’état ici.
const [selectedCountry, setSelectedCountry] = useState('');
const [availableCities, setAvailableCities] = useState([]);
const [selectedCity, setSelectedCity] = useState('');
const [otherCountry, setOtherCountry] = useState('');
-
L’état
selectedCountry
est déclaré et sa valeur initiale est définie sur une chaîne vide. -
L’état
availableCities
est déclaré et sa valeur initiale est définie sur un tableau vide. -
L’état
selectedCity
est déclaré et sa valeur initiale est définie sur une chaîne vide. -
L’état
otherCountry
est déclaré et sa valeur initiale est définie sur une chaîne vide.
Gestion des Événements
Dans le processus de sélection dans le menu déroulant, nous voulons que certaines actions soient exécutées. Les gestionnaires d’événements nous permettent de le faire dans le cas d’un événement, qui dans ce cas est l’événement onChange
.
const handleCountryChange = (e) => {
const country = e.target.value;
setSelectedCountry(country);
setAvailableCities(cities[country] || []);
setSelectedCity('');
if (country !== 'Other') {
setOtherCountry('');
}
};
Voici ce qui se passe dans la fonction handleCountryChange
:
-
Récupère la valeur de l’option sélectionnée dans le menu déroulant (le pays qui a été sélectionné).
-
Le
setSelectedCountry
met à jour la variable d’état (selectedCountry) avec le pays nouvellement sélectionné. -
cities[country]
recherche la liste des villes pour le pays sélectionné dans l’objetcities
.-
Si
cities[country]
est trouvé, il définit cette liste de villes comme les villes disponibles. -
Si aucune ville n’est trouvée pour le pays sélectionné (
cities[country]
est indéfini), le|| []
garantit qu’un tableau vide ([]
) est utilisé comme solution de secours, empêchant les erreurs lors de l’affichage des villes.
-
-
Lorsque l’utilisateur modifie la sélection du pays, la fonction
setSelectedCity
réinitialise leselectedCity
à une chaîne vide. -
Si le pays sélectionné n’est pas « Autre », l’état
otherCountry
est réinitialisé à une chaîne vide. Cela garantit que si l’utilisateur avait précédemment saisi quelque chose dans le champ « Autre », ce texte est effacé une fois qu’il sélectionne un pays différent (par exemple, « USA » ou « Canada »).
Pour la sélection du pays « Autre », nous devons juste garder une trace de la valeur saisie dans le champ. La fonction setOtherCountry
met à jour la valeur saisie. Et voici comment c’est fait :
const handleOtherCountryChange = (e) => {
setOtherCountry(e.target.value);
};
Pour le changement de villes, nous n’avons pas besoin de faire grand-chose car le pays sélectionné détermine quelles villes sont affichées. Tout ce que nous devons faire est de mettre à jour le selectedCity
avec la valeur de l’option sélectionnée dans la liste déroulante, qui est la ville sélectionnée.
Dans React, la fonction de mise à jour s’occupe de la mise à jour des variables d’état, donc le setSelectedCity
gère cela dans ce cas.
La fonction handleCityChange
sera :
const handleCityChange = (e) => {
setSelectedCity(e.target.value);
};
Retourner du JSX
Le composant DependentDropdown
rend trois éléments principaux : le menu déroulant des pays, le menu déroulant des villes et le champ de texte pour le pays.
Un menu déroulant en HTML est une combinaison des éléments <select>
et <option>
. Pour suivre la valeur des éléments, nous allons attacher des variables d’état à ceux-ci afin de pouvoir les contrôler. Faire cela est appelé ‘Contrôler les éléments’, tandis que les éléments eux-mêmes sont appelés ‘Éléments contrôlés’ dans React.
Pour contrôler l’élément <select>
du pays, nous allons lui donner un attribut value
de selectedCountry
et également attacher la fonction handleCountryChange
à celui-ci.
<label htmlFor="country" className='font-bold'>Select Country: </label>
<select id="country" value={selectedCountry} onChange={handleCountryChange}>
<option value="">Select a country</option>
{countries.map((country) => (
<option key={country.id} value={country.name}>
{country.name}
</option>
))}
</select>
De plus,
-
À l’intérieur du
<option>
, nous parcourons le tableaucountries
et créons dynamiquement un<option>
pour chaque objet pays dans le tableau. -
Le
name
de chaque pays est affiché comme le texte de l’option. -
La
key
de chaque option est définie sur l’id
du pays et lavalue
est définie sur lename
du pays. -
La
key
aide React à gérer la liste de manière efficace lors du re-rendu.
Le menu déroulant des villes est rendu conditionnellement en fonction du pays sélectionné. Si l’option de pays ‘Autre’ est choisie, un champ de saisie de texte est affiché pour que l’utilisateur précise le pays. Sinon, si un pays valide est sélectionné, un menu déroulant des villes avec des options pertinentes est affiché.
{selectedCountry === 'Other' ? (
<>
<label htmlFor="other-country" className='font-bold'>Please specify the country: </label>
<input
id="other-country"
type="text"
value={otherCountry}
onChange={handleOtherCountryChange}
placeholder="Enter country name"
/>
</>
) : (
selectedCountry && (
<>
<label htmlFor="city" className='font-bold'>Select City: </label>
<select id="city" value={selectedCity} onChange={handleCityChange}>
<option value="">Select a city</option>
{availableCities.map((city, index) => (
<option key={index} value={city}>
{city}
</option>
))}
</select>
</>
)
)
}
De plus :
-
Nous vérifions si
selectedCountry
est l’option ‘Autre’ et affichons un champ de saisie de texte. -
Le champ de saisie de texte a un état
otherCountry
et la fonction gestionnairehandleOtherCountryChange
qui lui est attachée. -
Nous contrôlons l’élément
<select>
des villes en utilisant l’attributvalue
, en le définissant sur la variable d’état deselectedCity
. Le gestionnaire d’événements,handleCityChange
, est également attaché pour gérer les événementsonChange
. -
Nous parcourons le tableau
availableCities
et créons dynamiquement un<option>
pour chaque ville du tableau. -
La clé de chaque option est définie sur un
index
et la valeur est définie sur lacity
. -
Chaque ville est affichée en tant que texte de l’option.
C’est tout ce que nous devons faire pour avoir un menu déroulant dépendant fonctionnel en utilisant nos données statiques.
Voici tout le code rassemblé :
import React, { useState } from 'react';
const DependentDropdown = () => {
// Données de pays statiques
const countries = [
{ id: 1, name: 'USA' },
{ id: 2, name: 'Canada' },
{ id: 3, name: 'Other' },
];
// Données de ville statiques correspondant aux pays
const cities = {
USA: ['New York', 'Los Angeles', 'Chicago'],
Canada: ['Toronto', 'Vancouver', 'Montreal'],
};
// État pour conserver le pays, la ville sélectionnée et tout autre texte de pays
const [selectedCountry, setSelectedCountry] = useState('');
const [availableCities, setAvailableCities] = useState([]);
const [selectedCity, setSelectedCity] = useState('');
const [otherCountry, setOtherCountry] = useState('');
// Gérer le changement de pays
const handleCountryChange = (e) => {
const country = e.target.value;
setSelectedCountry(country);
setAvailableCities(cities[country] || []);
setSelectedCity('');
if (country !== 'Other') {
setOtherCountry('');
}
};
// Gérer le changement de ville
const handleCityChange = (e) => {
setSelectedCity(e.target.value);
};
// Gérer le changement de saisie d'un autre pays
const handleOtherCountryChange = (e) => {
setOtherCountry(e.target.value);
};
return (
<div className='text-center text-3xl'>
<h1 className='font-extrabold text-5xl p-10'>Dependent Dropdown Example</h1>
{/* Menu déroulant de pays */}
<label htmlFor="country" className='font-bold'>Select Country: </label>
<select id="country" value={selectedCountry} onChange={handleCountryChange}>
<option value="">Select a country</option>
{countries.map((country) => (
<option key={country.id} value={country.name}>
{country.name}
</option>
))}
</select>
{/* Ville ou saisie d'un autre pays */}
{selectedCountry === 'Other' ? (
<>
<label htmlFor="other-country" className='font-bold'>Please specify the country: </label>
<input
id="other-country"
type="text"
value={otherCountry}
onChange={handleOtherCountryChange}
placeholder="Enter country name"
/>
</>
) : (
selectedCountry && (
<>
<label htmlFor="city" className='font-bold'>Select City: </label>
<select id="city" value={selectedCity} onChange={handleCityChange}>
<option value="">Select a city</option>
{availableCities.map((city, index) => (
<option key={index} value={city}>
{city}
</option>
))}
</select>
</>
)
)}
</div>
);
};
export default DependentDropdown;
Étape 3 : Utiliser le composant
Pour obtenir vos résultats finaux, vous devez importer le composant DependentDropdown
dans votre App.js
ou App.jsx
et le placer à l’intérieur de la section de retour du composant App.
import DependentDropdown from './DependentDropdown'
function App() {
return (
<DependentDropdown/>
)
}
export default App
N’oubliez pas de lancer l’application en entrant l’une de ces commandes :
npm start //pour créer une application react
npm run dev //pour une application react vite
Enfin, voici ce qui devrait s’afficher dans votre navigateur :
Gestion des données dynamiques (requêtes API)
Dans les applications du monde réel, les listes des menus déroulants ne sont peut-être pas statiques. Au lieu de cela, elles peuvent être récupérées à partir d’une API ou d’un fichier JSON agissant comme une API.
Dans cet exemple, nous lirons des données à partir d’un fichier JSON pour peupler notre menu déroulant dépendant. Cette pratique présente certains avantages qui sont :
-
Charge de base de données réduite: En utilisant un fichier JSON statique (ou un fichier préchargé), vous réduisez le nombre de requêtes à la base de données qui seraient sinon nécessaires pour remplir les menus déroulants. C’est particulièrement utile si les options de menu déroulant sont assez statiques et ne changent pas souvent.
-
Rendu plus rapide de l’IU: Puisque les données sont déjà côté client, il n’est pas nécessaire d’effectuer une requête aller-retour vers le serveur à chaque interaction de l’utilisateur avec le menu déroulant. Cela peut rendre l’interface plus réactive.
Notre fichier JSON contient des états et des LGAs (Local Government Areas), qui sont l’équivalent de pays et de villes.
Les données dans le fichier JSON sont représentées sous forme d’un tableau d’objets, chaque objet ayant des clés pour état, alias et lgas. La clé ‘lgas’ contient un tableau.
Voici comment cela est représenté:
[
{
"state": "Adamawa",
"alias": "adamawa",
"lgas": [
"Demsa",
"Fufure",
"Toungo",
"Yola North",
"Yola South"
]
},
{
"state": "Akwa Ibom",
"alias": "akwa_ibom",
"lgas": [
"Abak",
"Uruan",
"Urue-Offong/Oruko",
"Uyo"
]
},
//le reste des objets
]
Cette méthode de création d’un menu déroulant dynamique dépendant à partir d’une API n’est pas trop différente de l’exemple précédent, à l’exception de quelques modifications mineures.
Voici comment nous avons récupéré et utilisé des données à partir d’un fichier JSON :
import React, { useEffect, useState } from "react";
function DependentDropdown() {
//déclaration des variables d'état globales
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
//récupération des données en utilisant le hook useEffect
useEffect(() => {
fetch("nigeria-state-and-lgas.json") //fichier JSON défini comme URL
.then((res) => res.json())
.then((data) => {
setData(data);
setLoading(false);
})
.catch((error) => {
console.error("Error fetching data:", error);
setLoading(false);
});
}, []);
return loading ? <div>Loading...</div> : <Form data={data} />;
}
//formulaire recevant des données en tant que props
function Form({ data }) {
//déclaration des variables d'état locales
const [selectedState, setSelectedState] = useState("");
const [selectedLga, setSelectedLga] = useState("");
const [showList, setShowList] = useState(false);
let sortedData = data.slice().sort((a, b) => a.state.localeCompare(b.state));
const selectedData = sortedData.find((item) => item.state === selectedState);
//fonction de gestion pour l'état
function handleClickState(e) {
setSelectedState(e.target.value);
setShowList(true);
}
//fonction de gestion pour Lga
function handleClickLga(e) {
setSelectedLga(e.target.value);
}
return (
<div>
<form onSubmit={handleFormSubmit}>
<div>
{/* Prénom */}
<div>
<label htmlFor="firstName">First Name</label>
<input type="text"
id="firstName"
name="firstName"
placeholder="Enter your first name"/>
</div>
{/* Nom de famille */}
<div>
<label htmlFor="lastName">
Last Name
</label>
<input
type="text"
id="lastName"
name="lastName"
placeholder="Enter your last name"/>
</div>
</div>
<div>
<div>
<select value={selectedState} onChange={handleClickState} name="state">
<option value="" disabled>Choose your state</option>
{sortedData.map((data) => (
<option key={data.alias} value={data.state}>
{data.state}
</option>
))}
</select>
</div>
{selectedData && showList && (
<select value={selectedLga} onChange={handleClickLga} name="lga">
<option value="" disabled>{`Choose your LGA in ${selectedState}`}</option>
{selectedData.lgas.map((lgass) => (
<option key={lgass} value={lgass}>
{lgass}
</option>
))}
</select>
)}
</div>
<div>
<button type="submit">
Submit
</button>
</div>
</form>
</div>
);
}
export default DependentDropdown;
La modification clé ici est la récupération des données en utilisant le useEffect
hook, qui récupère les données d’état et LGA uniquement lors du premier rendu
Voici comment cela s’affiche dans le navigateur :
Conclusion
Dans ce tutoriel, vous avez appris comment créer des menus déroulants dépendants en React en utilisant à la fois des données statiques et dynamiques. Vous pouvez maintenant utiliser ce type de menu déroulant dans vos applications React.
Si vous avez trouvé cet article utile, vous pouvez me contacter sur LinkedIn pour plus d’articles et publications liés à la programmation.
A bientôt !
Source:
https://www.freecodecamp.org/news/how-to-build-dependent-dropdowns-in-react/