• 티스토리 홈
  • 프로필사진
    redpome
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
redpome
  • 프로필사진
    redpome
    • 분류 전체보기 (50)
      • 내일배움캠프 (23)
      • 웹개발 지식 (2)
      • 프로그래머스 (8)
      • React (7)
      • 코딩테스트 (1)
      • UI-UX (1)
      • 타입스크립트 (2)
      • Next.js (3)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • TIL - UseContext 사용기, 트러블 슈팅
        2025년 02월 06일
        • redpome
        • 작성자
        • 2025.02.06.:57

        Props를 넘겨주면서 사용하는 방식에서 Context를 통해 전역에서 상태를 관리하기로 했다.

        https://github.com/PomegranateBlue/pokedex

         

        GitHub - PomegranateBlue/pokedex: 1세대 포켓몬 도감

        1세대 포켓몬 도감. Contribute to PomegranateBlue/pokedex development by creating an account on GitHub.

        github.com


        Props-drilling 브랜치에서 벗어나 context 브랜치에서 작업을 했다. Context의 사용 목적에 맞게 사용했냐고 물어보면 그렇지는 않았다. 단지 Props를 전달하는 방식에서 벗어난 방법을 연습한다고 생각하고 마구잡이로 코드를 작성했다. 공통적으로 사용할 데이터가 무엇인지에 대해 고민했어야했는데 그렇지 못한 것 같다.

         

        Dex 컴포넌트에 Provider 주입

         

        const Dex = () => {
          const [pokemonInBall, setPokemonInBall] = useState([]);
        
          const addPokemonCard = (id) => {
            const selectedCard = POKEMON_DATA.find((card) => card.id === id);
            if (pokemonInBall.includes(selectedCard)) {
              alert("같은 포켓몬은 1마리만!");
              return;
            }
            if (selectedCard) {
              if (pokemonInBall.length >= 6) {
                alert("최대 6마리까지 데리고 다닐 수 있습니다");
                return;
              }
              setPokemonInBall((selectedPokemon) => [...selectedPokemon, selectedCard]);
            }
          };
          const deletePokemonCard = (id) => {
            setPokemonInBall((prevPokemon) =>
              prevPokemon.filter((card) => card.id !== id)
            );
          };
          return (
            <PokemonContext.Provider
              value={{
                pokemonInBall,
                deletePokemonCard,
                addPokemonCard,
                POKEMON_DATA,
              }}
            >
              <Container>
                <DashBoard />
                <PokemonList></PokemonList>
              </Container>
            </PokemonContext.Provider>
          );
        };
        
        export default Dex;

         

        Dex 컴포넌트의 하위 컴포넌트로는 Dashboard, PokemonList가 있고, PokemonList에는 PokemonCard가 존재한다. 원래대로라면 객체 리터럴을 사용해서 부모-자식 컴포넌트간 Props를 전달해주어야하지만 Context API를 통해 Dex 컴포넌트를 감싸고나면 Props 전달없이 컴포넌트에서 필요로하는 데이터를 사용할  수 있다.

         

        const DashBoard = () => {
          const { pokemonInBall, deletePokemonCard } = useContext(PokemonContext);
          const maxPokemon = 6;
          return (
        ...
          );
        };
        
        export default DashBoard;

         

        Dashboard 컴포넌트에서의 Context 사용방법이다. 해당 컴포넌트에서는 포켓몬 카드를 추가했을때의 상태를 위한 PokemonInBall과 카드를 삭제시키는 deletePokemonCard를 호출하고있다. import 방식과 유사하게 필요한 상태나 함수 등을 불러와 사용할  수 있다.

         

        Props 방식을 꼭 기피하는 것 보다는 공통적인 데이터가 무엇이 될지를 선택해야하고 동적인 데이터를 Context를 통해 전달해주는 것이 Context API의 목적에 맞는 것이라 할 수 있다.

         

        const PokemonCard = ({ pokemonData }) => {
        ...

         

        PokemonCard의 경우에는 Props를 통해 넘겨주게 된 것도 그런 이유라고 할 수 있다.

        포켓몬 카드의 정보는 외부 파일로부터 호출해서 사용한다, 따라서 포켓몬 카드의 정보는 정적인 데이터로 굳이 Context API를 통해 전달해줄 이유가 없어진다. 따라서 Props 전달 방식을 통해 개별 카드의 구조를 만들고 그런 카드들을 리스트로 렌더링하는 것이 맞다.

         

        Context를 사용하면서 막혔던 부분이라면 이 부분이라고 할 수 있다. 왜냐하면 Context로 넘겨줄 데이터가 아닌데도 카드 컴포넌트에서 구현을 하려고했으니 말이다.

         

        e.stopPropagation()

        자바스크립트를 배울때 이벤트 위임과 전파는 꽤나 많이 들어봤다, 오랜만에 맞닥뜨린 문제인데 여기서 볼 줄은 몰랐다.

        거북왕

        위의 거북왕 카드는 카드 자체를 클릭할 때와 추가 버튼을 눌렀을 때 이벤트를 발생시킨다. 문제는 뭐였냐면 추가 버튼을 누르면 카드의 상세정보 이벤트가 발생한다는 점이다.

         

              <PokemonCardFrame
                onClick={(e) => {
                e.stopPropagation();
                showPokemonDetail(pokemonData.id);}}>
                <CardButton
                  onClick={(e) => {
                    e.stopPropagation();
                    addPokemonCard(pokemonData.id);}}>
                  추가
                </CardButton>

         

        PokemonCardFrame을 클릭하면 발생하는 이벤트와 CardButton을 클릭하면 발생하는 이벤트가 있는데 이 둘은 현재 부모-자식 관계이다. 따라서 이벤트 전파가 발생하여 자식 컴포넌트의 클릭 이벤트가 부모의 클릭이벤트까지 발생시키게된다.

        이럴때 사용하는 것이 이벤트 전파를 막는 e.stopPropagation()이다.

        '내일배움캠프' 카테고리의 다른 글

        뉴스피드 프로젝트 - (1)  (0) 2025.02.12
        포켓몬 도감 트러블 슈팅 - 카드 중복 에러  (0) 2025.02.11
        포켓몬 도감 만들기 -(1)  (0) 2025.02.05
        TIL - 트러블 슈팅  (0) 2025.01.23
        실행 컨텍스트 (3) - 콜 스택, 마이크로 태스크  (0) 2025.01.17
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바