Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3주차 기본/심화 과제] 🌼 짱구는 못말려! 폭풍을 부르는 카드게임 대격돌 💖 #8

Merged
merged 28 commits into from
May 12, 2023

Conversation

simeunseo
Copy link
Member

@simeunseo simeunseo commented May 4, 2023

🔗 구현 페이지

✨ 구현 기능 명세

  • 기본 과제

    • 게임 난이도 선택

      • 난이도 종류 (easy, normal, hard) 구현
      • 난이도가 중간에 바뀌면 카드 모두 뒤집어서 처음으로 돌아가기
    • 종답 수 노출

      • (현재 나의 스코어) / 전체 정답 으로 상단에 노출
    • 카드 선택

      • 2개의 카드를 선택하면 다른 카드는 선택할 수 없음
      • 선택한 카드가 정답이면 정답 스코어 증가, 카드 뒤집힌 채로 유지
      • 선택한 카드가 오답이면 카드를 다시 뒷면으로 돌리기
    • 카드 배열 순서

      • 카드가 배열되는 순서는 랜덤으로 지정
      • 난이도에 따라 지정되는 쌍도 랜덤으로 지정
  • 심화 과제

    • 애니메이션

      • 카드 선택시 뒤집어지는 기깔나는 애니메이션 적용
      • 카드 쌍을 맞추면 현재 스코어에 애니메이션
    • theme + styled-components 적용

      • globalstyle 사용
      • theme 사용
    • 게임 초기화 버튼

      • '리셋' 버튼을 누르면 모든 설정이 처음으로 돌아감
    • createPortal

      • 모든 카드 맞추기가 끝난 후 보여주는 모달을 Portal을 활용해 만듦

🌼 PR Point

  • 폴더 구조

    기능 하나하나를 만들 때마다 어떤 파일을 어느 폴더에 넣을지 결정하는게 참 어려웠어요! 결과적으로 이런 폴더 구조가 나왔는데 어떤가요? 사실 컴포넌트 구조를 전혀 생각하지 않고 시작해서 모듈화가 제대로 안되었어요 ㅠㅠ

    📁 src
    ㄴ 📁 assets
      ㄴ 📁 cardImages
      ㄴ 📁 pageImages
      ㄴ bgm.mp3
    ㄴ 📁components
      ㄴ Audio.jsx
      ㄴ Buttons.jsx
      ㄴ Card.jsx
      ㄴ Cards.jsx
      ㄴ Header.jsx
      ㄴ ModalPortal.jsx
      ㄴ SuccessModal.jsx
    ㄴ 📁context
      ㄴ context.jsx
    ㄴ 📁 hooks
      ㄴ useDidMountEffect.js
    ㄴ 📁 pages
      ㄴ Main.jsx
    ㄴ 📁 styles
      ㄴ globalStyles.js
      ㄴ theme.js
    ㄴ 📁 utils
      ㄴ getCardArr.js
    
  • 상태 관리

    저는 전역 상태 관리를 하는게 뭔가 발전된(?) 형태인 줄 알고 처음에 그렇게 시작을 했는데, 웨비들 말을 들어보니 그래도 처음엔 prop drilling 부터 해보는게 학습에 있어서는 더 좋다고 하더라구요!! 그래서 그말을 듣고 prop을 내려주는 방식으로 구현했습니다. 다들 뭔가 전역으로 관리하는게 편법이라는 식으로 말하든데 저는 아직 그게 더 어렵네요;;
    그래서 결과적으로 난이도(level)와 점수(score)는 contextAPI+useReducer를 통해 전역으로 관리했고, 나머지는 전부 prop으로 넘겨주었습니다. 근데 생각과제 하면서 보니까 contextAPI는 변동이 많은 데이터에는 적합하지 않다네요..? 아차차.... 아무튼 그래도 prop이 아닌 다른 상태 관리 방식을 사용해볼 수 있는 좋은 기회였습니다! (context/context.jsx)에 있습니다!

  • 난이도에 따른 랜덤 카드 추출

    이 부분을 4가지 함수로 구현했어요!

    • utils/getCardArr.js

      //0부터 totalNum까지의 숫자 중 selectNum개의 랜덤한 숫자 리스트를 반환하는 함수
      const getRandomIdx = (totalNum, selectNum) => {
        let randomIndexArray = [];
        for (let i = 0; i < selectNum; i++) {
          //이미 추출된 숫자인지 확인한다
          let randomNum = Math.floor(Math.random() * totalNum);
          if (randomIndexArray.indexOf(randomNum) === -1) {
            randomIndexArray.push(randomNum);
          } else {
            //이미 추출된 숫자라면 다시 뽑는다
            i--;
          }
        }
        return randomIndexArray;
      };

      가져올 이미지의 인덱스를 랜덤으로 선택하기 위해, 랜덤한 숫자 리스트를 생성하는 함수입니다.

      //arr 요소들을 두개씩으로 복제하고 랜덤으로 섞는 함수
      const makeCardDeck = (array) => {
        array.map((item) => {
          array.push(item); //두개씩 복제
        });
        shuffle(array); //무작위 섞기
        return array;
      };

      같은 카드를 두장씩 보여줘야하므로 array의 요소를 두개씩 복제한 뒤 랜덤으로 섞는 함수입니다.

      const shuffle = (array) => {
        for (let i = array.length - 1; i > 0; i--) {
          let j = Math.floor(Math.random() * (i + 1));
          [array[i], array[j]] = [array[j], array[i]];
        }
      };

      random() 메소드에는 편향이 있다는 글을 보고 다른 방식을 찾아서 shuffle 함수를 따로 구현하였습니다! 출처

      const getCardArr = (level) => {
        let randomIdxArr = [];
        let totalLength = allImageArr.length;
      
        switch (level) {
          case "easy":
            randomIdxArr = makeCardDeck(getRandomIdx(totalLength, 5));
            return randomIdxArr;
          case "normal":
            randomIdxArr = makeCardDeck(getRandomIdx(totalLength, 7));
            return randomIdxArr;
          case "hard":
            randomIdxArr = makeCardDeck(getRandomIdx(totalLength, 9));
            return randomIdxArr;
          default:
            randomIdxArr = makeCardDeck(getRandomIdx(totalLength, 5));
            return randomIdxArr;
        }
      };

      이것이 최종적으로 난이도를 인자로 받아서 카드 목록을 반환해주는 함수입니다!

  • Card 컴포넌트

    카드의 state에 따라서 style을 변경해주어야 하기 때문에, 특정 state에 따라서 카드의 뒤집히는 스타일링과 관련된 className을 넣어서 해결했습니다.

    • components/Card.jsx

      const Card = (props) => {
        const { imgId, clickHandler, compareList, pairedList, pk } = props;
      
        // 이 카드가 비교되고 있는 카드인지 여부를 체크하여 boolean 값을 반환
        const isComparing = compareList.some((item) => {
          if (item.pk === pk) return true;
        });
        // 이 카드가 이미 짝맞춰진 카드인지 여부를 체크하여 boolean 값을 반환
        const isPaired = pairedList.some((item) => {
          if (item.pk === pk) return true;
        });
      
        return (
          <StyledCardWrapper>
            <div className="pair">
              <div className={`card ${isComparing || isPaired ? "flipped" : ""}`}>
                <div className="card__front">
                  <StyledCard src={allImageArr[imgId]}></StyledCard>
                </div>
                <div className="card__back">
                  <StyledCard
                    onClick={() => clickHandler(pk, imgId)}
                    src={cardBackImage}
                  ></StyledCard>
                </div>
              </div>
            </div>
          </StyledCardWrapper>
        );
      };
      여기서 prop으로 넘겨받은 compareList가 현재 비교대상에 해당하는 카드 목록이고, pairedList는 이미 정답을 맞춘 카드 목록입니다. 이 상태에 해당하는 카드들은 앞면으로 뒤집어주어야 하기 때문에, ${isComparing || isPaired ? "flipped" : ""}라는 구문에서 "flipped"라는 className을 붙여주게 됩니다!
  • Cards 컴포넌트

    Card 컴포넌트를 매핑하여 최종적으로 전체 카드 리스트를 관리하는 가장 핵심적인 부분입니다.

    • 카드 클릭 핸들링

      const clickHandler = (pk, imgId) => {
          let tempCompareList = [];
          let tempPairedList = [];
          switch (compareList.length) {
            case 0: // 첫번째 선택
              tempCompareList = [...compareList];
              tempCompareList.push({ pk, imgId });
              // compareList에 삽입
              setCompareList(tempCompareList);
      
              break;
            case 1: // 두번째 선택
              tempCompareList = [...compareList];
              tempCompareList.push({ pk, imgId });
              // compareList에 삽입
              setCompareList(tempCompareList);
      
              // 두번째 선택이 첫번째 선택과 같은 카드일 경우
              if (compareList[0].imgId === imgId) {
                scoreDispatch({ type: "INCREASE" }); // 점수 올리기
      
                tempPairedList = [...pairedList];
      
                // compareList의 요소들을 pairedList로 옮긴다
                tempCompareList.forEach((item) => {
                  const pk = item.pk;
                  const imgId = item.imgId;
                  tempPairedList.push({ pk, imgId });
                });
                setPairedList(tempPairedList);
      
                // compairList 초기화
                setCompareList([]);
              } else {
                // 오답
                setTimeout(() => {
                  setCompareList([]);
                }, 800);
              }
              break;
          }
        };
      이 코드가 바로 카드의 클릭을 관리하는 부분인데요! 기본적으로 compareListpairedList라는 두가지 상태로 카드의 상태를 관리합니다.
      compareList에 아무것도 들어있지 않다면 아직 선택한 카드가 없다는 뜻이에요. 이 상태에서 카드를 클릭하게 되면 첫번째로 고른 카드이므로 compareList에 추가합니다.
      두번째 선택을 했을 때는 비교가 필요합니다. 따라서 imgId(이미지에 따라 부여한 아이디)를 비교하여 정답이라면 score에 대한 dispatch를 통해 점수를 올리고, 짝이 지어진 쌍을 pairedList로 옮깁니다!! 그리고 비교가 끝났으므로 compareList에서는 삭제해주는 겁니다!!!
      만약 오답이라면 setTimeout으로 800ms의 시간이 지난 뒤 compareList에서 해당 카드들을 삭제합니다. 이렇게하면 800ms 뒤에 카드가 다시 뒤집히게 됩니다.
      자, 다시 보시면, Card 컴포넌트에서는 현재 이 카드가 비교되고 있는 카드인지 아니면 이미 정답이 맞춰진 카드인지를 알기 위해서 해당 카드의 pk라는 요소를 참조하고 있고, Cards 컴포넌트에서는 같은 이미지인지 아닌지를 비교하기 위해서 해당 카드의 imgId라는 요소를 참조하고 있습니다. 즉, 한 카드에 대한 고유한 키(pk)와 이미지를 나타내는 아이디(imgId)가 둘다 필요했던 것입니다. 따라서 저는 compareListpairedList라는 상태에 해당 카드의 {pk, imgId} 쌍을 넣음으로써 두가지 정보를 사용할 수 있었습니다.
  • 점수에 따른 애니메이션

    이 부분은 거의 유일하게(?) 다른 코드를 참고하지 않고 제가 고안한 로직인데요...ㅋㅋㅋ 그래서 다른 분들은 어떻게 구현했는지 궁금!!
    일단 score를 주시하고 있다가 이게 변하면 애니메이션을 추가해야되는거니까, 세미나에서 배웠던 useRef와 useEffect를 활용해봤습니다! 그래서 score를 나타내는 부분에 animationScore라는 ref를 추가해서 선택해주고, useEffect를 통해 score라는 값이 변경되면 animationScore.current.classList.toggle("animiation")을 통해 animation이라는 className을 추가함으로써 애니메이션을 넣을 수 있었습니다. 그런데 이 때 처음 마운트 될 때도 애니메이션이 발생하는걸 막기 위해서 custom hook을 만들어 사용했습니다. (hooks/useDidMountEffect.js에 있어요!) 참고 (근데 서현이 PR 보니깐 score가 0이면 그냥 return해버리는 방법이 있네요.. ㄴㅇㄱ)

  • 자랑하고 싶은 디테일

    • 배경 음악

      들어가보시면 왼쪽 상단에 플레이어가 하나 있어요~ 짱구 오프닝을 넣어봤답니다~ 자동재생하고 싶어서 이것저것 엄청 찾아봤는데 브라우저 자체에서 차단하고 있는거라 해결하기가 어렵더라구요ㅠㅠ 그래서 일단 플레이어를 넣는걸로 해결~~
    • 난이도 변경, 리셋 시 카드 목록 변경에 딜레이 주기

      그니깐 난이도 변경이나 리셋을 하면 카드가 다시 뒤집히면서 초기화되잖아요? 근데 다시 뒤집힐때도 뒤집히는 애니메이션이 생기는데 그 뒤집히는 잠깐의 찰나동안 새로 바뀐 카드 앞면이 노출이 되더라구요... 처음엔 그냥 난이도 변경이나 리셋시에는 애니메이션이 적용되지 않도록 하고싶었는데 좀 복잡해지는 것 같아서, 선택한 방법은 setTimeout으로 카드 목록 변경에 딜레이를 주는 것이었습니다. 그러니까 카드가 뒤집히는 애니메이션이 끝났을 때 비로소 카드가 변경되어요.
    • 디자인 귀엽죠!!!

      디자인에 몇 시간을 쓴거지...

🥺 소요 시간, 어려웠던 점

  • 30h 제가 이번에 시간을 재면서 해봤거든요...? 진짜 30시간이나 걸렸어요... 🤣😇🤢🥹 많이 부족한만큼 열심히 했습니다 더 성장하겠어요!!!
  • 정말.. 정말 모든 것이 어려워서 어떤 걸 꼽아야 할지 모르겠어요ㅠㅠ 근데 일단 가장 막막했던건.. 그냥 진짜 시작하는게 제일 막막했어요. "뭘 어디에 만들어야할지!!!" 이게 진짜 감이 안잡히는거예요 그래서 초반에 진짜 울뻔했어요... 그래도 리액트를 찍먹 시작한지는 꽤 된 것 같은데 항상 벽만 두드리는 기분이었거든요. 아무~~리 강의를 들어도 실제로 뭘 만들려고 하면 아 무슨 state를 어떻게 만들어야 하는지, 상태 관리를 어떻게 해야 하는지, 대체 무슨 컴포넌트를 어디에 만들어야 하는지, 어떤 파일을 만들어야하고, 어디서 어디로 prop을 넘겨주어야하는지 이 모든 것이 정말 막막했어요. 그런데 이번 과제가 그동안 모호하게만 알고있던 개념들을 체화할 수 있는 정말 소중한 기회였습니다.
  • 그래서 제가 선택한 방법은 역시 남의 코드 참고하기였는데요... 찬우 오빠가 가장 먼저 올려가지구 아무래도 가장 많이 참고를 했습니다 ㅎㅎ 특히 카드 상태를 관리하는 로직은 찬우 오빠 코드와 많이 유사함을 솔직하게 밝힙니다!! 다음부터는 시작하기 전에 어떤 컴포넌트와 어떤 state를 만들고, 어떤식으로 구조를 형성할지 미리 직접 고민해봐야겠습니다.
  • 아쉬운 점 중 하나는, Buttons 컴포넌트 안에 Score를 넣어버렸다는 거예요.. 제 화면 설계상 난이도 고르는 버튼이랑 리셋 버튼 사이에 점수를 나타내는 영역이 들어가야 했는데, 처음에 버튼을 한번에 구현하면서 난이도 버튼이랑 리셋 버튼을 Buttons라는 컴포넌트에 한번에 묶어버렸더니 Score 컴포넌트도 그 안에 낑겨넣게 됐어요 ㅠㅠ 미리 생각해서 설계했다면 좋았을텐데요!!
  • 물어볼거 있어요!!!
    스크린샷 2023-05-06 오전 12 35 01
    이거 오버레이 화면 높이 꽉 채우는거 대체 어떻게 하는거죠...? 100vh나 100%로 하면 그냥 딱 화면 높이만큼만 되어서 스크롤을 하면 밑에 빈 공간이 생겨요ㅠㅠ -> position:fixed로 해결!!!! 현수가 알려줬숩니다 고마워요

🌈 구현 결과물

🔗 구현 페이지

  • 게임 플레이

_AdobeExpress.2.mp4
  • 리셋 기능 (카드 목록이 변경된다)

_AdobeExpress.mp4

@simeunseo simeunseo changed the title Week3/#1 [3주차 기본/심화 과제] 🌼 짱구는 못말려! 폭풍을 부르는 카드게임 대격돌 💖 May 5, 2023
@simeunseo simeunseo requested review from kwonET and borimong May 5, 2023 15:02
@simeunseo simeunseo self-assigned this May 5, 2023
@simeunseo simeunseo marked this pull request as ready for review May 5, 2023 15:03
Copy link

@borimong borimong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

본격적인 리뷰 전에 일단 넘넘 수고 많았다구 넘 잘하구 있다고 말해주고 싶어여..!!!! 리액트가 익숙하지 않으면 정말 어려웠을텐데 끝까지 포기하지 않고 해낸 모습이 넘 멋찌다!!!!! 배포까지 야무지게 하구 ㅎㅎ QA 해 봤는데 같은 카드를 두 번 연속 클릭하면 뒤집혀진 상태가 유지되는 오류가 있어서 요것 한 번 수정해 보면 좋겠다!!! 짱구 배경음악은 어떻게 넣을 생각을 했지..? 진짜 똑똑이 그 자체,,,💞💞 저랑 같이 열심히 리팩토링 해 보아요 😄🌸🐰

Copy link

@kwonET kwonET left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context나 커스텀 훅에 대해서 안 써봤는데, 덕분에 이렇게 쓰는 거구나를 깨닫고 가 ~!
또 지역/전역 상태 관리를 통해서 컴포넌트를 다루는 과정에서 다양한 방법이 있는 걸 알고
좀 더 내 코드를 다른 방면으로 수정해볼 수도 있겠다는 생각이 든다!!

수고했어 은서 ㅎㅎ 디자인도 최고 !!
우리 금잔디조 폼 미쳐따이

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설마 헤더 만든 거니....
정말 은서의 열정은 못말려😵‍💫😵‍💫😵‍💫!! 🔥🔥🔥

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미쳐써 미쳐써 열정 미쳐써....

Comment on lines +27 to +30
// 카드가 뒤집어지는 잠깐의 시간동안 새로 달라진 카드가 노출되지 않게 하기 위해, 카드 목록이 바뀔 때까지 약간의 딜레이를 준다.
setTimeout(() => {
setCardAllList(getCardArr(levelType));
}, 800);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 정말 디테일하다!!

Comment on lines +107 to +108
default:
return 5;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디폴트는 이지로 해준 것도 엄청 꼼꼼해~~


const score = useContext(ScoreContext);

// 첫 렌더링 때는 useEffect를 적용하지 않도록 custom hook을 사용함!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이럴 때 커스텀 훅을 만들어서 useEffect를 조정할 수 있구나 -!!!

import { useRef } from "react";
import { useState } from "react";

const Button = (props) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하나의 Button 컴포넌트를 만들어두고, 한 파일 안에서 재사용할 수도 있구나!

근데 궁금한 점은 이렇게 한 파일에서 여러 컴포넌트를 만들어서 사용하는 경우가 자주 있나 궁금해~
나는 이번에 거의 한 파일에 한 컴포넌트만 넣어줬는데, 너무 잘게 분리되면 관리가 어렵다는 단점이 있겠다는 생각도 들고!
뭐가 더 나은 접근 방식일까???

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아 나도 고민이 됐는데... 일단 나는 Button 컴포넌트가 이 파일 외에 다른데서는 쓰이지 않으니 이 안에 묶어두었어
그런데 만들다보면 다른데 쓰이는 상황이 생길수도 있으니까 초기에 설계를 잘해야될 것 같아!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약 Button 이 다른 곳에서도 공통으로 쓰인다면 common 폴더를 만들고 그 안에 파일을 만들어서 쓰는 게 좋을 것 같구 그게 아니라면 그냥 메인이 되는 것 하위에 styled component 로 버튼을 만드는 것이 더 깔끔할 것 같긴 해!! 아무래도 컴포넌트가 여러 개면 뭐가 메인인지 찾는데 시간도 걸리고 하니까..!!! :)

Comment on lines +149 to +172
const Buttons = (props) => {
const { setCompareList, setPairedList, setCardAllList } = props;

return (
<>
<ButtonContainer>
<LevelButtons
setCompareList={setCompareList}
setPairedList={setPairedList}
/>
<RightGroupWrapper>
<Score />
<ResetButton
setCompareList={setCompareList}
setPairedList={setPairedList}
setCardAllList={setCardAllList}
/>
</RightGroupWrapper>
</ButtonContainer>
</>
);
};

export default Buttons;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pr 에 써준대로 버튼이라는 컴포넌트치고는 점수라는 다른 컴포넌트도 얽혀있는 느낌이 들긴 한다 🥹

Button 컴포넌트들을 Main에선 LevelButtons을, Header(예시)에선 Score, ResetButton 이렇게 따로 렌더링해도 좋았을 것 같은 느낌~!

혹시 한 컴포넌트에서 export {LevelButtons, ResetButton} 이런식으로 내보내 줄수도 있나 궁금하네 !! (뭔가 안될 것 같은 느낌이지만)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우앗 개선 방식 같이 고민해줘서 고마워 ㅎㅎ
앗 맞아 한 파일에서 여러개의 컴포넌트를 내보낼 수 있더라! 대신 default 는 한 모듈당 하나만 있어야한대

switch (compareList.length) {
case 0: // 첫번째 선택
tempCompareList = [...compareList];
tempCompareList.push({ pk, imgId });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

나는 이미지 url과 고유한 이미지 키를 관리하기 위해 두가지 상태를 썼는데,
이렇게 한 객체로 묶어서 하나의 상태로 관리해주는 법도 있다는 걸 알아가 ~!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뭔가 저 쌍이 의미하는 바가 직관적이진 않아서 이게 괜찮은 방법인진 모르겠지만..! 시도해보았다~ key,value 쌍으로 넣으면 좀 더 명확할거같당

@simeunseo simeunseo merged commit 890fbaa into main May 12, 2023
Copy link

@borimong borimong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

은서 언니 넘넘 수고 많아따..!! 기회 되면 코멘트 단 부분들 리팩토링 해보면 좋을 것 같야!!! 진짜 디자인도 완전 열심히하구 열정 대박이라 넘 멋져..🥹🥹

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미쳐써 미쳐써 열정 미쳐써....

);
};

export default Audio;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 오디오까지.. 정성 대박이다...

import { useRef } from "react";
import { useState } from "react";

const Button = (props) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약 Button 이 다른 곳에서도 공통으로 쓰인다면 common 폴더를 만들고 그 안에 파일을 만들어서 쓰는 게 좋을 것 같구 그게 아니라면 그냥 메인이 되는 것 하위에 styled component 로 버튼을 만드는 것이 더 깔끔할 것 같긴 해!! 아무래도 컴포넌트가 여러 개면 뭐가 메인인지 찾는데 시간도 걸리고 하니까..!!! :)

};

const ResetButton = (props) => {
const { setCompareList, setPairedList, setCardAllList } = props;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컴포넌트로 분리시키니까 이런 setState 하나하나 props 로 받아와야해서 좀 번거로운 감이 있다..!! 한 번 하나의 함수 내에서 styled component 로 만드는 것 시도해 보면 좋을 것 같아!! :)

return (
<StyledCardWrapper>
<div className="pair">
<div className={`card ${isComparing || isPaired ? "flipped" : ""}`}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flipped 여부를 판단하는 state 를 만들어봐도 좋을 것 같댜!!! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants