> 웹 프론트엔드 > CSS 튜토리얼 > React를 사용하여 국가 찾기 애플리케이션 구축

React를 사용하여 국가 찾기 애플리케이션 구축

DDD
풀어 주다: 2024-09-13 14:15:26
원래의
1070명이 탐색했습니다.

Building a Country Finder Application with React

소개

이 블로그 게시물에서는 React를 사용하여 Country Finder 애플리케이션을 구축하는 방법을 살펴보겠습니다. 이 애플리케이션을 사용하면 사용자는 국가를 검색하고 지역별로 필터링하며 각 국가에 대한 자세한 정보를 볼 수 있습니다. 우리는 React의 후크와 컨텍스트를 활용하여 상태와 테마를 관리하고 REST Countries API와 통합하여 국가 데이터를 가져올 것입니다.

프로젝트 개요

국가 찾기 애플리케이션은 사용자가 다음을 수행할 수 있는 대화형 인터페이스를 제공합니다.

  • 국가 이름으로 검색하세요.
  • 지역별로 국가를 필터링하세요.
  • 국기, 인구 등 각 국가에 대한 자세한 정보를 확인하세요.

특징

  • 검색창: 사용자가 이름으로 국가를 검색할 수 있습니다.
  • 지역별 필터링: 지역을 기준으로 국가를 필터링하는 드롭다운 메뉴
  • 국가 세부정보: 선택한 국가에 대한 세부 정보를 표시합니다.
  • 테마 전환: 밝은 테마와 어두운 테마 간에 전환합니다.

사용된 기술

  • React: 사용자 인터페이스 구축을 위한 JavaScript 라이브러리.
  • REST 국가 API: 국가에 대한 데이터를 제공합니다.
  • CSS: 애플리케이션 스타일을 지정합니다.
  • React Router: 페이지 간 이동 및 상태 전달용.

프로젝트 구조

이 프로젝트는 여러 구성요소로 구성됩니다.

  • App.js: 라우팅을 위한 헤더와 아웃렛을 포함하는 주요 구성 요소입니다.
  • Header.js: 애플리케이션 제목과 테마 전환 버튼을 표시합니다.
  • Home.js: 검색 및 필터 옵션과 국가 목록이 포함된 메인 페이지
  • SearchBar.js: 국가 검색을 위한 구성 요소입니다.
  • SelectMenu.js: 지역별로 국가를 필터링하기 위한 드롭다운 메뉴
  • CountriesList.js: 검색 및 필터 기준에 따라 국가 목록을 표시합니다.
  • CountryCard.js: 각 국가의 요약을 표시합니다.
  • CountryDetail.js: 선택한 국가에 대한 자세한 정보를 보여줍니다.
  • CountryDetailShimmer.js: 국가 세부정보에 대한 자리 표시자를 로드하는 중입니다.
  • Error.js: 경로에 대한 오류 처리 구성 요소.

설치

  1. 저장소 복제:
   git clone https://github.com/abhishekgurjar-in/country-finder.git
   cd country-finder
로그인 후 복사
  1. 종속성 설치:
   npm install
로그인 후 복사
  1. 개발 서버 시작:
   npm start
로그인 후 복사

용법

  1. 국가 검색: 검색창에 국가 이름을 입력하여 국가 목록을 필터링하세요.
  2. 지역별 필터링: 드롭다운 메뉴에서 지역을 선택하면 해당 지역의 국가를 볼 수 있습니다.
  3. 세부정보 보기: 국가 카드를 클릭하면 해당 국가에 대한 자세한 정보를 볼 수 있습니다.

코드 설명

App.js

App 구성 요소는 ThemeProvider 내에서 Header 및 Outlet 구성 요소를 래핑하여 애플리케이션 전체에서 테마 상태를 관리합니다.

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;
로그인 후 복사

헤더.js

헤더 구성요소를 사용하면 사용자는 밝은 테마와 어두운 테마 사이를 전환하고 애플리케이션 제목을 표시할 수 있습니다.

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

홈 구성 요소에는 검색 창, 필터 메뉴가 포함되어 있으며 검색 및 필터 기준에 따라 국가가 나열됩니다.

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

SearchBar 구성 요소는 국가 검색을 위한 사용자 입력을 처리합니다.

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

SelectMenu 구성요소는 지역별로 국가를 필터링할 수 있는 드롭다운을 제공합니다.

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>
  )
}
로그인 후 복사

국가목록.js

CountriesList 구성 요소는 국가 목록을 가져와 표시합니다.

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

CountryDetail 구성 요소는 선택한 국가에 대한 자세한 정보를 가져와 표시합니다.

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

CountryDetailShimmer 구성 요소는 국가 세부 정보를 가져오는 동안 로딩 자리 표시자를 표시합니다.

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>
  );
}
로그인 후 복사

컨트리카드.js

CountryCard 구성 요소는 각 국가에 대한 간략한 개요를 표시합니다.

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>
  );
}
로그인 후 복사

국가목록Shimmer.js

CountriesListShimmer 구성 요소는 국가 목록을 가져오는 동안 로딩 자리 표시자를 표시합니다.

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>
  );
}
로그인 후 복사

라이브 데모

Country Finder Demo를 방문하면 Country Finder 애플리케이션의 라이브 데모를 볼 수 있습니다.

결론

이 프로젝트에서는 사용자가 국가를 검색하고, 지역별로 필터링하고, 자세한 정보를 볼 수 있는 국가 찾기 애플리케이션을 React를 사용하여 구축했습니다. REST Countries API와 통합하고 React의 후크와 컨텍스트를 사용하여 상태와 테마를 관리했습니다.

크레딧

  • 반응: 반응
  • REST 국가 API: REST 국가
  • Font Awesome: Font Awesome

작가

Abhishek Gurjar는 실용적이고 기능적인 웹 애플리케이션 제작에 열정을 쏟는 헌신적인 웹 개발자입니다. GitHub에서 더 많은 프로젝트를 확인해 보세요.

위 내용은 React를 사용하여 국가 찾기 애플리케이션 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿