Recent Posts
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
관리 메뉴

개발자 박가나

[241108 TIL] 본캠프 28일차 ('포켓몬 도감 만들기' 프로젝트 3일차) 본문

내일배움캠프

[241108 TIL] 본캠프 28일차 ('포켓몬 도감 만들기' 프로젝트 3일차)

gnchoco97 2024. 11. 8. 20:26

  📌 오늘의 TIL
  • [포켓몬 도감] 프로젝트

 

 

 [포켓몬 도감] 프로젝트 

코드 리팩토링. props drilling 방식을 Context API 방식으로 변경

Context API를 이용해서 state를 전역적으로 관리해준다.

/* context/PokemonContext.js */

import { createContext } from 'react';

export const PokemonContext = createContext(null);
/* Dashboard.js */

import { useContext } from 'react';
import { PokemonContext } from '../context/PokemonContext';

export default function Dashboard() {
    const { myPokemons } = useContext(PokemonContext);

    return (
        <Container>
            <Title>나만의 포켓몬</Title>
            <BallContainer>
                {myPokemons.map((pokemon) => {
                    return <PokemonCard key={pokemon.id} type={'my'} pokemon={pokemon} />;
                })}
                {[...Array(6 - myPokemons.length)].map(() => {
                    return <PokemonBall key={uuid()} />;
                })}
            </BallContainer>
        </Container>
    );
}
/* PokemonCard.js */

import { useContext } from 'react';
import { PokemonContext } from '../context/PokemonContext';

export default function PokemonCard({ type = 'list', pokemon }) {
    const { handleAdd, handleDelete } = useContext(PokemonContext);

    /* 카드 내 버튼 클릭 이벤트 */
    const handleClick = (e) => {
        // 이벤트 버블링 방지
        e.stopPropagation();

        type === 'list' ? handleAdd(pokemon) : handleDelete(pokemon);
    };

    return (
        <Container onClick={() => navigate(`/detail/${pokemon.id}`)}>
            <Character src={pokemon.img_url} />
            <Name>{pokemon.korean_name}</Name>
            <Description>No. {String(pokemon.id).padStart(3, '0')}</Description>
            <Button type="sub" bgcolor="red" label={type === 'list' ? '추가' : '삭제'} handleClick={handleClick} />
        </Container>
    );
}

 

기능 구현. 상세 정보 페이지에서 나만의 포켓몬 추가 및 삭제하기

Dex 페이지 뿐만 아니라 Detail 페이지에서도 나만의 포켓몬 추가 및 삭제가 가능하게 해준다.

/* Detail.js */

import { useNavigate, useParams } from 'react-router-dom';
import styled from 'styled-components';
import Button from '../components/Button';
import MOCK_DATA from '../Data';
import { useContext, useEffect, useState } from 'react';
import { PokemonContext } from '../context/PokemonContext';

export default function Detail() {
    const { myPokemons, handleAdd, handleDelete } = useContext(PokemonContext);

    const [label, setLabel] = useState('');

    useEffect(() => {
        const isAdd = myPokemons.length && !!myPokemons.find((item) => item.id === Number(param.id));
        setLabel(isAdd ? '삭제' : '추가');
    }, [myPokemons, param.id]);

    return (
        <>
            {pokemon && (
                <Wrap>
                    <Character src={pokemon.img_url} alt="character" />
                    <Name>{pokemon.korean_name}</Name>
                    <Description>
                        타입 :{' '}
                        {pokemon.types.map((type, index) => {
                            return index < pokemon.types.length - 1 ? `${type}, ` : type;
                        })}
                    </Description>
                    <Description>{pokemon.description}</Description>
                    <ButtonContainer>
                        <Button bgcolor="red" label={label} handleClick={() => (label === '추가' ? handleAdd(pokemon) : handleDelete(pokemon))} />
                        <Button bgcolor="black" label="뒤로 가기" handleClick={() => navigate('/dex')} />
                    </ButtonContainer>
                </Wrap>
            )}
        </>
    );
}