Dans cet article de blog, nous explorerons comment créer une application Country Finder à l'aide de React. Cette application permet aux utilisateurs de rechercher des pays, de les filtrer par région et d'afficher des informations détaillées sur chaque pays. Nous utiliserons les hooks et le contexte de React pour gérer l'état et les thèmes, et nous intégrerons l'API REST Countries pour récupérer les données des pays.
L'application Country Finder fournit une interface interactive où les utilisateurs peuvent :
Le projet est organisé en plusieurs composantes :
git clone https://github.com/abhishekgurjar-in/country-finder.git cd country-finder
npm install
npm start
Le composant App enveloppe les composants Header et Outlet dans un ThemeProvider, gérant l'état du thème dans l'application.
import Header from "./components/Header"; import { Outlet } from "react-router-dom"; import "./App.css"; import { ThemeProvider } from "./contexts/ThemeContext"; const App = () => { return ( <ThemeProvider> <Header /> <Outlet /> </ThemeProvider> ); }; export default App;
Le composant Header permet aux utilisateurs de basculer entre les thèmes clairs et sombres et affiche le titre de l'application.
import { useTheme } from "../hooks/useTheme" export default function Header() { const [isDark, setIsDark] = useTheme(); return ( <header className={`header-container ${isDark ? 'dark' : ''}`}> <div className="header-content"> <h2 className="title"> <a href="/">Country Finder</a> </h2> <p className="theme-changer" onClick={() => { setIsDark(!isDark); localStorage.setItem('isDarkMode', !isDark); }}> <i className={`fa-solid fa-${isDark ? 'sun' : 'moon'}`} /> {isDark ? 'Light' : 'Dark'} Mode </p> </div> </header> ) }
Le composant Accueil contient la barre de recherche, le menu de filtrage et répertorie les pays en fonction des critères de recherche et de filtrage.
import React, { useState } from 'react'; import SearchBar from './SearchBar'; import SelectMenu from './SelectMenu'; import CountriesList from './CountriesList'; import { useTheme } from '../hooks/useTheme'; export default function Home() { const [query, setQuery] = useState(''); const [isDark] = useTheme(); return ( <main className={`${isDark ? 'dark' : ''}`}> <div className="search-filter-container"> <SearchBar setQuery={setQuery} /> <SelectMenu setQuery={setQuery} /> </div> <CountriesList query={query} /> </main> ) }
Le composant SearchBar gère les saisies utilisateur pour la recherche de pays.
import React from 'react'; export default function SearchBar({ setQuery }) { return ( <div className="search-container"> <i className="fa-solid fa-magnifying-glass"></i> <input onChange={(e) => setQuery(e.target.value.toLowerCase())} type="text" placeholder="Search for a country..." /> </div> ) }
Le composant SelectMenu fournit une liste déroulante pour filtrer les pays par région.
import React from 'react'; export default function SelectMenu({ setQuery }) { return ( <select className="filter-by-region" onChange={(e) => setQuery(e.target.value.toLowerCase())}> <option hidden>Filter by Region</option> <option value="Africa">Africa</option> <option value="Americas">Americas</option> <option value="Asia">Asia</option> <option value="Europe">Europe</option> <option value="Oceania">Oceania</option> </select> ) }
Le composant CountriesList récupère et affiche une liste de pays.
import React, { useEffect, useState } from 'react'; import CountryCard from './CountryCard'; import CountriesListShimmer from './CountriesListShimmer'; export default function CountriesList({ query }) { const [countriesData, setCountriesData] = useState([]); useEffect(() => { fetch('https://restcountries.com/v3.1/all') .then((res) => res.json()) .then((data) => { setCountriesData(data); }); }, []); if (!countriesData.length) { return <CountriesListShimmer />; } return ( <div className="countries-container"> {countriesData .filter((country) => country.name.common.toLowerCase().includes(query) || country.region.toLowerCase().includes(query) ) .map((country) => ( <CountryCard key={country.name.common} name={country.name.common} flag={country.flags.svg} population={country.population} region={country.region} capital={country.capital?.[0]} data={country} /> ))} </div> ) }
Le composant CountryDetail récupère et affiche des informations détaillées sur un pays sélectionné.
import React, { useEffect, useState } from 'react'; import { Link, useLocation, useParams } from 'react-router-dom'; import { useTheme } from '../hooks/useTheme'; import CountryDetailShimmer from './CountryDetailShimmer'; import './CountryDetail.css'; export default function CountryDetail() { const [isDark] = useTheme(); const params = useParams(); const { state } = useLocation(); const countryName = params.country; const [countryData, setCountryData] = useState(null); const [notFound, setNotFound] = useState(false); function updateCountryData(data) { setCountryData({ name: data.name.common || data.name, nativeName: Object.values(data.name.nativeName || {})[0]?.common, population: data.population, region: data.region, subregion: data.subregion, capital: data.capital, flag: data.flags.svg, tld: data.tld, languages: Object.values(data.languages || {}).join(', '), currencies: Object.values(data.currencies || {}) .map((currency) => currency.name) .join(', '), borders: [], }); if (!data.borders) { data.borders = []; } Promise.all( data.borders.map((border) => fetch(`https://restcountries.com/v3.1/alpha/${border}`) .then((res) => res.json()) .then(([borderCountry]) => borderCountry.name.common) ) ).then((borders) => { setTimeout(() => setCountryData((prevState) => ({ ...prevState, borders })) ); }); } useEffect(() => { if (state) { updateCountryData(state); return; } fetch(`https://restcountries.com/v3.1/name/${countryName}?fullText=true`) .then((res) => res.json()) .then(([data]) => { if (!data) { setNotFound(true); } else { updateCountryData(data); } }) .catch(() => setNotFound(true)); }, [countryName, state]); if (notFound) { return ( <div className={`error-container ${isDark ? 'dark' : ''}`}> <h3>Country not found</h3> <Link to="/">Back to home</Link> </div> ); } if (!countryData) { return <CountryDetailShimmer />; } return ( <div className={`country-detail-container ${isDark ? 'dark' : ''}`}> <Link to="/" className="back-button"> <i className="fa-solid fa-arrow-left" /> Back </Link> <div className="country-detail-content"> <img src={countryData.flag} alt={`${countryData.name} flag`} /> <div className="country-detail-info"> <h1>{countryData.name}</h1> <div className="details"> <p><strong>Native Name:</strong> {countryData.nativeName}</p> <p><strong>Population:</strong> {countryData.population}</p> <p><strong>Region:</strong> {countryData.region}</p> <p><strong>Subregion:</strong> {countryData.subregion}</p> <p><strong>Capital:</strong> {countryData.capital}</p> <p><strong>Top Level Domain:</strong> {countryData.tld}</p> <p><strong>Languages:</strong> {countryData.languages}</p> <p><strong>Currencies:</strong> {countryData.currencies}</p> <p><strong>Border Countries:</strong> {countryData.borders.join(', ') || 'None'}</p> </div> </div> </div> </div> ); }
Le composant CountryDetailShimmer affiche un espace réservé de chargement lors de la récupération des détails du pays.
import React from 'react'; export default function CountryDetailShimmer() { return ( <div className="country-detail-shimmer"> <div className="shimmer-img"></div> <div className="shimmer-info"> <div className="shimmer-line name"></div> <div className="shimmer-line"></div> <div className="shimmer-line"></div> <div className="shimmer-line"></div> <div className="shimmer-line"></div> </div> </div> ); }
Le composant CountryCard affiche un bref aperçu de chaque pays.
import React from 'react'; import { Link } from 'react-router-dom'; export default function CountryCard({ name, flag, population, region, capital, data }) { return ( <div className="country-card"> <img src={flag} alt={`${name} flag`} /> <h3>{name}</h3> <p><strong>Population:</strong> {population}</p> <p><strong>Region:</strong> {region}</p> <p><strong>Capital:</strong> {capital}</p> <Link to={`/country/${name}`} state={data}> <button>More Details</button> </Link> </div> ); }
Le composant CountriesListShimmer affiche un espace réservé de chargement lors de la récupération de la liste des pays.
import React from 'react'; export default function CountriesListShimmer() { return ( <div className="countries-list-shimmer"> {Array.from({ length: 10 }).map((_, index) => ( <div key={index} className="shimmer-card"></div> ))} </div> ); }
Vous pouvez voir une démo en direct de l'application Country Finder en visitant Country Finder Demo.
Dans ce projet, nous avons créé une application Country Finder à l'aide de React qui permet aux utilisateurs de rechercher des pays, de les filtrer par région et d'afficher des informations détaillées. Nous avons intégré l'API REST Countries et utilisé les hooks et le contexte de React pour gérer l'état et les thèmes.
Abhishek Gurjar est un développeur Web dévoué et passionné par la création d'applications Web pratiques et fonctionnelles. Découvrez plus de ses projets sur GitHub.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!