Rumah  >  Artikel  >  hujung hadapan web  >  Membina Aplikasi Pencari Negara dengan React

Membina Aplikasi Pencari Negara dengan React

DDD
DDDasal
2024-09-13 14:15:261006semak imbas

Building a Country Finder Application with React

pengenalan

Dalam catatan blog ini, kami akan meneroka cara membina aplikasi Country Finder menggunakan React. Aplikasi ini membolehkan pengguna mencari negara, menapisnya mengikut wilayah dan melihat maklumat terperinci tentang setiap negara. Kami akan menggunakan cangkuk dan konteks React untuk mengurus keadaan dan tema, dan kami akan menyepadukan dengan REST Countries API untuk mengambil data negara.

Gambaran Keseluruhan Projek

Aplikasi Country Finder menyediakan antara muka interaktif di mana pengguna boleh:

  • Cari negara mengikut nama.
  • Tapis negara mengikut wilayah.
  • Lihat maklumat terperinci tentang setiap negara, termasuk bendera, populasi dan banyak lagi.

Ciri-ciri

  • Bar Carian: Membenarkan pengguna mencari negara mengikut nama.
  • Tapis mengikut Wilayah: Menu lungsur turun untuk menapis negara berdasarkan rantau mereka.
  • Butiran Negara: Memaparkan maklumat terperinci tentang negara yang dipilih.
  • Togol Tema: Tukar antara tema terang dan gelap.

Teknologi yang Digunakan

  • React: Pustaka JavaScript untuk membina antara muka pengguna.
  • REST Countries API: Menyediakan data tentang negara.
  • CSS: Untuk menggayakan aplikasi.
  • Penghala Reaksi: Untuk menavigasi antara halaman dan keadaan berlalu.

Struktur Projek

Projek ini disusun kepada beberapa komponen:

  • App.js: Komponen utama yang termasuk Pengepala dan Outlet untuk penghalaan.
  • Header.js: Memaparkan tajuk aplikasi dan butang togol tema.
  • Home.js: Halaman utama dengan pilihan carian dan penapis serta senarai negara.
  • SearchBar.js: Komponen untuk mencari negara.
  • SelectMenu.js: Menu lungsur turun untuk menapis negara mengikut rantau.
  • CountriesList.js: Memaparkan senarai negara berdasarkan kriteria carian dan penapis.
  • CountryCard.js: Memaparkan ringkasan setiap negara.
  • CountryDetail.js: Menunjukkan maklumat terperinci tentang negara yang dipilih.
  • CountryDetailShimmer.js: Memuatkan pemegang tempat untuk butiran negara.
  • Error.js: Ralat mengendalikan komponen untuk laluan.

Pemasangan

  1. Klon repositori:
   git clone https://github.com/abhishekgurjar-in/country-finder.git
   cd country-finder
  1. Pasang kebergantungan:
   npm install
  1. Mulakan pelayan pembangunan:
   npm start

Penggunaan

  1. Cari Negara: Masukkan nama negara dalam bar carian untuk menapis senarai negara.
  2. Tapis mengikut Wilayah: Pilih rantau daripada menu lungsur turun untuk melihat negara di rantau itu.
  3. Lihat Butiran: Klik pada kad negara untuk melihat maklumat terperinci tentang negara itu.

Penerangan Kod

App.js

Komponen Apl membungkus komponen Pengepala dan Outlet dalam Pembekal Tema, mengurus keadaan tema merentas aplikasi.

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;

Header.js

Komponen Pengepala membolehkan pengguna menogol antara tema terang dan gelap serta memaparkan tajuk aplikasi.

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>
  )
}

Home.js

Komponen Laman Utama mengandungi bar carian, menu penapis dan menyenaraikan negara berdasarkan kriteria carian dan penapis.

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>
  )
}

SearchBar.js

Komponen SearchBar mengendalikan input pengguna untuk mencari negara.

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>
  )
}

SelectMenu.js

Komponen SelectMenu menyediakan menu lungsur untuk menapis negara mengikut rantau.

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>
  )
}

CountriesList.js

Komponen CountriesList mengambil dan memaparkan senarai negara.

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>
  )
}

CountryDetail.js

Komponen CountryDetail mengambil dan memaparkan maklumat terperinci tentang negara yang dipilih.

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>
  );
}

CountryDetailShimmer.js

Komponen CountryDetailShimmer menunjukkan pemegang tempat memuatkan semasa mengambil butiran negara.

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>
  );
}

CountryCard.js

Komponen CountryCard memaparkan gambaran keseluruhan ringkas setiap negara.

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>
  );
}

CountriesListShimmer.js

Komponen CountriesListShimmer menunjukkan pemegang tempat memuatkan semasa mengambil senarai negara.

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>
  );
}

Demo Langsung

Anda boleh melihat demo langsung aplikasi Country Finder dengan melawati Country Finder Demo.

Kesimpulan

Dalam projek ini, kami membina aplikasi Country Finder menggunakan React yang membolehkan pengguna mencari negara, menapisnya mengikut wilayah dan melihat maklumat terperinci. Kami menyepadukan dengan REST Countries API dan menggunakan cangkuk dan konteks React untuk mengurus keadaan dan tema.

Kredit

  • React: React
  • API Negara REST: Negara REST
  • Fon Hebat: Font Hebat

Pengarang

Abhishek Gurjar ialah pembangun web berdedikasi yang bersemangat untuk mencipta aplikasi web yang praktikal dan berfungsi. Lihat lebih banyak projek beliau di GitHub.

Atas ialah kandungan terperinci Membina Aplikasi Pencari Negara dengan React. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn