예비군 끝나고 급하게 해설 영상 참고하면서 짰다.
전 세계 API 불러오기
import axios from "axios";
import { Country } from "../types/country";
export const getCountries = async (): Promise<Country[]> => {
const response = await axios.get("https://restcountries.com/v3.1/all");
return response.data;
};
axios get메서드를 이용해서 전 세계 국가들의 정보를 호출
필요한 데이터 타입 지정하기
export interface Country {
name: {
common: string;
};
capital: string[];
translations: {
[key: string]: {
official: string;
};
};
flags: {
svg: string;
};
}
원래 모든 데이터들의 타입을 지정했으나 굳이 그럴 필요 없을 것 같아서 필요한 데이터와 타입만 남겨둠
App.tsx
import React from "react";
import CountryList from "./components/CountryList";
import "./App.css";
const App: React.FC = () => {
return (
<section className="bg-sky-300 font-jua text-base">
<div className="w-[1280px] my-0 mx-auto ">
<CountryList />
</div>
</section>
);
};
export default App;
CountryList.tsx
import { useEffect, useState } from "react";
import { getCountries } from "../api/countries";
import { Country } from "../types/country";
import CountryCard from "./CountryCard";
const CountryList: React.FC = () => {
const [countries, setCountries] = useState<Country[]>([]);
const [selectedCountries, setSelectedCountries] = useState<Country[]>([]);
// 특정 나라를 클릭하면 따로 선택된 나라로 올라가고
// 다시 해당 나라를 클릭하면 다시 내려오도록 하는 함수
const handleSelectCountry = (country: Country): void => {
if (
!selectedCountries.find(
(selectedCountry: Country) =>
selectedCountry.name.common === country.name.common
)
) {
setSelectedCountries([...selectedCountries, country]);
setCountries(
countries.filter((prevcountry: Country) => {
return prevcountry.name.common !== country.name.common;
})
);
} else {
setSelectedCountries(
selectedCountries.filter((selectedCountry: Country) => {
return selectedCountry.name.common !== country.name.common;
})
);
setCountries([country, ...countries]);
}
};
// 전 세계 나라 정보 불러오기
useEffect(() => {
const getAllCountries = async () => {
try {
const data: Country[] = await getCountries();
setCountries(data);
} catch (error) {
console.error("나라 데이터를 불러오는데에 실패했습니다 : ", error);
alert("데이터를 불러오는 데에 실패했습니다.");
}
};
getAllCountries();
}, []);
return (
<>
<div className="flex flex-col justify-center items-center gap-4">
<div className="flex justify-center items-center w-full bg-white border-solid border-4 border-black rounded-md">
<h1 className="text-3xl">전 세계 모든 나라</h1>
</div>
<div className="w-full flex flex-col justify-center items-center bg-white border-solid border-4 border-black rounded-md">
<h1 className="text-red-700 text-2xl p-4">주적</h1>
<div className=" w-full p-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{selectedCountries.map((country: Country) => {
return (
<CountryCard
key={country.name.common}
country={country}
handleSelectedCountry={handleSelectCountry}
/>
);
})}
</div>
</div>
<div className="w-full flex flex-col justify-center items-center bg-white border-solid border-4 border-black rounded-md">
<h1 className="text-green-700 text-2xl p-4">그 외</h1>
<div className="w-full p-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{countries.map((country: Country) => {
return (
<CountryCard
key={country.name.common}
country={country}
handleSelectedCountry={handleSelectCountry}
/>
);
})}
</div>
</div>
</div>
</>
);
};
export default CountryList;
CountryCard.tsx
import { Country } from "../types/country";
interface CountryCardProps {
country: Country;
handleSelectedCountry: (country: Country) => void;
}
const CountryCard: React.FC<CountryCardProps> = ({
country,
handleSelectedCountry,
}) => {
return (
<div
className="bg-slate-200 flex flex-col justify-center items-center gap-1 border-solid border-2 border-black p-4 rounded-md"
onClick={() => handleSelectedCountry(country)}
>
<img className="w-40 h-20" src={country.flags.svg} />
<h1 className="text-xl">{country.translations.kor.official}</h1>
<h3 className="text-lg">{country.capital}</h3>
</div>
);
};
export default CountryCard;
모든 컴포넌트들은 tailwind css 를 이용해서 디자인
이제 vercel을 이용해 배포
결과
급하게 해서 이전에 했던 지출 내역 앱의 UI와 비슷하게 구성했다.
뭔가 아쉽다.
시간이 있었더라면 다른 데이터들을 이용해서 나라이름 등의 기준으로 정렬할 수 있는 기능을 넣었을 수도 있었을 것 같다.