# 7-2-3. Evolution Chain API ## src/hooks/useEvolutionChain.ts `src` 디렉토리 하위에 `/hooks` 를 생성하고, 그 하위에 포켓몬 진화 정보를 가져오는 커스텀 훅\(`/useEvolutionChain.ts`\)을 추가합니다. **Evolution Chain API \(**https://pokeapi.co/api/v2/evolution-chain/{id}**\)** 는 포켓몬 진화 정보 **id** 를 받아 해당 진화 정보를 반환합니다. ### Species API `https://pokeapi.co/api/v2/pokemon-species/{id or name}` 로 **포켓몬의 종\(species\) 정보를 호출**하면 해당 포켓몬의 진화 정보를 반환합니다. ![예시](../../../.gitbook/assets/2021-08-22-4.39.48.png) **useEvolutionChain** hook 에서는 위 evolution\_chain 의 url 을 입력받아 `useQuery` 로 진화 정보를 가져와보겠습니다. ```jsx import axios, { AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; import { UseQueryResult } from 'react-query/types/react/types'; import { EvolutionChainResponse } from '../types'; const useEvolutionChain = (url?: string): UseQueryResult, Error> => ( useQuery(['evolution', { url }], () => url ? axios.get(url) : null) ) export default useEvolutionChain; ``` 아래와 같이 사용할 수 있습니다. ```jsx const { isSuccess, isError, isLoading, data } = useEvolutionChain(url); ``` 미리 만들어 둔 **src/components/Evolution.tsx** 컴포넌트에 적용해보겠습니다. ```jsx import React, { useEffect, useState } from 'react'; import styled from '@emotion/styled/macro'; import { Chain, Color } from '../types'; import EvolutionStage from './EvolutionStage'; import { mapColorToHex } from '../utils'; import useEvolutionChainQuery from "../hooks/useEvolutionChainQuery"; type Props = { isLoading: boolean; id?: string; color?: Color; url?: string; } const Base = styled.div` margin-top: 32px; padding: 0 20px 20px; `; const Title = styled.h4<{ color: string }>` margin: 0; padding: 0; font-size: 20px; font-weight: bold; color: ${({ color }) => color}; `; const ImageWrapper = styled.div` width: 100%; height: 160px; display: flex; justify-content: center; align-items: center; `; const Image = styled.img` width: 120px; height: 120px; object-fit: contain; `; const List = styled.ul` list-style: none; margin: 20px 0 0 0; padding: 0; > li + li { margin-top: 24px; } `; const EmptyWrapper = styled.div` display: flex; justify-content: center; align-items: center; width: 100%; height: calc(100vh - 444px); `; const Empty = styled.div<{ color: string }>` color: ${({ color }) => color}; `; const Evolution: React.FC = ({ url, color }) => { const { isSuccess, isError, isLoading, data } = useEvolutionChainQuery(url); const [evolutionChain, setEvolutionChain] = useState>([]); useEffect(() => { const makeEvolutionChain = (chain: Chain) => { if (chain.evolves_to.length) { const [evolvesTo] = chain.evolves_to; const from = chain.species; const to = evolvesTo.species; const level = evolvesTo.evolution_details[0].min_level; setEvolutionChain(prev => [...prev, { from, to, level }]); makeEvolutionChain(chain.evolves_to[0]); } } isSuccess && data && makeEvolutionChain(data.data.chain); return (): void => { setEvolutionChain([]); } }, [isSuccess, data]); return ( Evolution { isLoading || isError ? ( ) : ( evolutionChain.length ? ( { evolutionChain.map(({ from, to, level }, idx) => ( )) } ) : ( This Pokémon does not evolve. ) ) } ) } export default Evolution; ```