-
Notifications
You must be signed in to change notification settings - Fork 0
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
base: main
Are you sure you want to change the base?
Conversation
useMemo() 훅 활용하여 cardList가 변경되지 않을 경우, 이전 값을 재 사용하도록 구현
JSON.parse(JSON.Stringify(obj)) 활용하여 깊은 복사가 가능하도록 수정
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아루밍 넘 고생해써!!! 마니 고민한게 잘 느껴져.....흑 진짜 고생해따 ㅜㅜ
week3/src/components/Button.jsx
Outdated
switch (isClick) { | ||
case 0: | ||
setCurrentPage(<CommonPage cardList={easyCardList} />); | ||
break; | ||
|
||
case 1: | ||
setCurrentPage(<CommonPage cardList={normalCardList} />); | ||
break; | ||
|
||
case 2: | ||
setCurrentPage(<CommonPage cardList={hardCardList} />); | ||
break; | ||
|
||
default: | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요거 isClick을 요기서 switch문으로 나누지 말고 요렇게 바로 넣고, 공통적인 함수로 수행할 수 있도록 리팩토링 할 수도 있을 것 같아! ㅎㅎ 밑에 mixCardList부분에도 달아놨당!!
switch (isClick) { | |
case 0: | |
setCurrentPage(<CommonPage cardList={easyCardList} />); | |
break; | |
case 1: | |
setCurrentPage(<CommonPage cardList={normalCardList} />); | |
break; | |
case 2: | |
setCurrentPage(<CommonPage cardList={hardCardList} />); | |
break; | |
default: | |
break; | |
} | |
setCurrentPage(<CommonPage cardList={mixCardList(isClick)} />); |
week3/src/constants/cardImgList.js
Outdated
function mixEasyCardList() { | ||
const mixedEasyCardList = cardImgList | ||
.sort(() => Math.random() - 0.5) | ||
.slice(0, 5); | ||
return mixedEasyCardList.concat(mixedEasyCardList); | ||
} | ||
|
||
function mixNormalCardList() { | ||
const mixedNormalCardList = cardImgList | ||
.sort(() => Math.random() - 0.5) | ||
.slice(0, 7); | ||
return mixedNormalCardList.concat(mixedNormalCardList); | ||
} | ||
|
||
function mixHardCardList() { | ||
const mixedHardCardList = cardImgList.sort(() => Math.random() - 0.5); | ||
return mixedHardCardList.concat(mixedHardCardList); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
머ㅓ 이런식으로...?! 아름이가 구현한 방식도 직관적이고 넘 좋은데 난 뭔가 공통된 기능을 수행하는 함수들은 하나로 묶는게 좋을 것 같다구 갠적으로 생각해써 ㅎㅎㅎ 취향차이일수도 ㅎㅎㅎㅎ
function mixEasyCardList() { | |
const mixedEasyCardList = cardImgList | |
.sort(() => Math.random() - 0.5) | |
.slice(0, 5); | |
return mixedEasyCardList.concat(mixedEasyCardList); | |
} | |
function mixNormalCardList() { | |
const mixedNormalCardList = cardImgList | |
.sort(() => Math.random() - 0.5) | |
.slice(0, 7); | |
return mixedNormalCardList.concat(mixedNormalCardList); | |
} | |
function mixHardCardList() { | |
const mixedHardCardList = cardImgList.sort(() => Math.random() - 0.5); | |
return mixedHardCardList.concat(mixedHardCardList); | |
} | |
function mixCardList(isClick) { | |
let cardNum; | |
switch (isClick) { | |
case 0: | |
cardNum = 5; | |
break; | |
case 1: | |
cardNum = 7; | |
break; | |
case 2: | |
cardNum = 9; | |
break; | |
default: | |
break; | |
} | |
const mixedCardList = cardImgList | |
.sort(() => Math.random() - 0.5) | |
.slice(0, cardNum); | |
return mixedCardList.concat(mixedCardList); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헐 구러네? 난 이 생각은 못했던 것 같아! 위에 switch 문빼고 이렇게 묶으니까 훨씬 기능도 직관적으로 잘 보여서 좋은 것 같아 나두 공통된 기능하는 함수들 하나로 묶으려고 생각 많이 했던 것 같은데 요건 몰랐네..~~ 리팩토링때 참고해야ㅜ지
week3/src/components/Button.jsx
Outdated
// 기본 난이도 'EASY'로 설정 | ||
const [isClick, setIsClick] = useState(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0, 1, 2로 난이도 구분하는건가? 그러면 아예 상수로 const EASY = 5
, const NORMAL = 7
요런식으로 선언하는건 어땡?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위에 현지 말대루 난이도 easy 가 0 이라서 기본 난이도 설정을 easy로 해두는걸 useState(0)으로 한건가??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SynthiaLee 웅 마자 난이도 0,1,2 로 구분하고 잇써! 그래서 기본 난이도 설정을 easy로 하려고 useState 기본 값을 0으로 한고야!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iamphj3 (아래 51~54 번째 줄) click한 값과 levelData의 인덱스가 같으면 해당 난이도가 선택됐다는 걸 나타내기 위해서 난이도를 0, 1, 2로 구분해줬어..!!
week3/src/components/Button.jsx
Outdated
const levelData = ["EASY", "NORMAL", "HARD"]; | ||
// 기본 난이도 'EASY'로 설정 | ||
const [isClick, setIsClick] = useState(0); | ||
const [currentPage, setCurrentPage] = useState(<CommonPage />); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
초기값에 currentPage
컴포넌트에 cardList
props 안들어가도 되는거야?! 밑에 난이도 설정에는 있길래!!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
초기값으로는 props없이 페이지만 리턴하고 아래서 난이도 별로 props를 준다고 생각해서 이렇게 구현했더..! 초기값에도 props를 주는게 좋을까?
<ResetButton | ||
type="button" | ||
onClick={() => { | ||
setShuffle((prev) => prev + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
왜 리셋버튼을 누르면 setShuffle에 +1을 하는거야??!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
나두 궁금!!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아! 이거 reset 버튼이 클릭될 때마다 위에 페이지들을 다시 렌더링시켜서 카드 배열을 변하게 해주려고 shuffle을 생성했어! 그래서 버튼이 클릭될 때마다 shuffle 값에 변화를 줘서 useEffect가 실행될 수 있게 구현해봤어..!!
<> | ||
<ChokiPokiHeader> | ||
<strong> 💗 쵸키랑 푸키를 맞춰주세요! 💗</strong> | ||
<AnswerCounter className={animate ? "scale" : ""}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
animate 이면 scale 효과를 주려고 넣은건강?! 그러면 그냥 요런식으로 props로 넘겨줘서 조건부로 스타일 적용할 수 있지 않으까??!
<AnswerCounter className={animate ? "scale" : ""}> | |
<AnswerCounter animate={animate}> |
week3/src/components/Modal.jsx
Outdated
@font-face { | ||
font-family: "UhBeeSe_hyun"; | ||
src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/[email protected]/UhBeeSe_hyun.woff") | ||
format("woff"); | ||
font-weight: normal; | ||
font-style: normal; | ||
} | ||
|
||
font-family: "UhBeeSe_hyun"; | ||
font-size: 1rem; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요것두 theme으로 적용해주쟈!!!
.card { | ||
position: relative; | ||
} | ||
|
||
.card .front { | ||
transform: rotateY(90deg); | ||
transition: all ease-in 0.1s; | ||
position: absolute; | ||
} | ||
|
||
.flipped .front { | ||
transform: rotateY(0deg); | ||
transition-delay: 0.1s; | ||
} | ||
|
||
.card .back { | ||
transition: all ease-in 0.1s; | ||
transition-delay: 0.1s; | ||
} | ||
|
||
.flipped .back { | ||
transform: rotateY(90deg); | ||
transition-delay: 0s; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요건 왜 js안에 안넣구 따로 css 파일로 빼준걸까??!?!?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
js에서 한번에 정의하기가 헷갈려서 css로 빼서 먼저 기능 구현하고 js에 넣으려고 했는데 그냥 올려버렸....ㅎㅎ 다시 해봐야쥥
}; | ||
return ( | ||
<div className="card"> | ||
<div className={flipped ? "flipped" : ""}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이것도 일케 바로 prop으로 넘겨주면된당!!!
<div className={flipped ? "flipped" : ""}> | |
<div flipped={flipped}> |
flippedCard.length === copiedCardList.length | ||
? setModalOn(true) | ||
: setModalOn(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flippedCard.length === copiedCardList.length | |
? setModalOn(true) | |
: setModalOn(false); | |
setModalOn(flippedCard.length === copiedCardList.length); |
요렇게 하면 좀 더 간결하게 쓸 수 있겠당!ㅎㅎ
{levelData.map((data, idx) => { | ||
return ( | ||
<LevelButton | ||
key={idx} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
키값 잊지않구 준거 칭찬해~!
const cardImgList = [ | ||
{ | ||
name: img_1, | ||
alt: "첫 번째 카드", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alt도 따로 줬구나! 나는 아예 name으로 alt에도 같이 쓸 수 있는걸 줘서 그걸 재활용했는데 alt랑 이름이랑 많이 다른거 아닌 경우에는 추천해!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
마쟈!! 그렇게 쓰는 것도 좋은 것 같아! 근데 alt는 이미지를 설명하는 글이라 좀 더 직관적이게 해주는게 좋다고 해서 따로 한글로 정의해줬어ㅎㅎ
|
||
return ( | ||
<> | ||
<Header counter={counter} length={copiedCardList.length / 2} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요기 현지가 위에 counter score로 바꾸는거 말한거처럼 length 도 �totalScore 같은걸로 바꿔주면 더 직관적일거 같아!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
죠아!
const flippedCard = document.getElementsByClassName("flipped"); | ||
|
||
// useMemo() 활용하여 cardList가 변경되지 않을 경우, 이전 값을 재사용하도록 구현 | ||
const copiedCardList = useMemo(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 useMemo 사용햇구나 싱기...!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
웅 useMemo에 dependency로는 cardList를 줘서 리스트가 변하지 않을 경우에는 카드 배열이 변하지 않도록 했어..!! 안그러면 카드를 하나 클릭할 때마다 계속 카드 배열이 변하더라구 흑흑
|
||
export default Modal; | ||
|
||
const ModalContainer = styled.div` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
div 대신 section 으로 시맨틱하게 바꿔도 좋을거 같아~!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
옹 코드 구현할 때 section 태그는 그룹화하는 역할이라고 생각을 해서 모달 생성에 section을 쓰는건 의도와 맞지 않다고 생각햇던 것 같아! 다시 잘 생각해보고 리팩토링때 참고할게!!
어디서 아루미처럼 큐티뽀쨕한 캐릭터를 들고왓서...🥺 수고해따아💓 |
🌈 기본 과제
✨
게임 난이도 선택
✨
정답 수 노출
✨
카드 선택
✨
카드 배열 순서
🌈 심화 과제
✨
애니메이션
카드를 선택
→ 뒤집어지는 기깔나는 애니메이션을 적용해주세요!!
카드 쌍을 맞춘 경우
→ 저는 현재 스코어가 빛나는 애니메이션을 적용했습니다! 마음대루!!
✨
theme
+styled-components
:: 적용globalstyle
theme
→ 전역에서 사용할 수 있도록 적용해보세요!
✨
게임 초기화 버튼
✨
createPortal
🌼 PR Point
🍟 카드 랜덤으로 출력
🍟 난이도 별 페이지 동적으로 구현
처음에는 난이도 별로 하나씩 페이지를 생성했었는데, 기능을 구현하면서 중복 코드가 너무 많이 생기게 되더라구요..!
난이도 별로 카드 리스트만 다르게 받을 수 있다면, 하나의 페이지를 두고 동적으로 사용할 수 있을 것 같았어요.
동적으로 페이지를 구현한다면 중복 코드도 없애고 코드 유지 보수도 쉽게 할 수 있을 것 같아서 동적으로 페이지를 구현하는 쪽으로 코드를 수정했습니다.
🍟 카드 쌍을 맞춘 경우 애니메이션 적용
animate가 true인 경우에만 className(scale)이 할당되고, 해당 className에 보여주고자 하는 애니메이션을 저장했어요.
결과적으로, 카드 쌍을 맞췄을 때 animate는 true → className: scale → 보여주고자 하는 애니메이션이 실행됩니다
🥺 소요 시간, 어려웠던 점
12h
🍟 하나의 카드 선택 시, 같은 이미지를 가진 카드가 공개됨
하나의 카드를 선택하니까 같은 이미지를 가진 카드가 공개돼버리는 문제가 있었습니다..! 이 부분을 어떻게 해결해야 할 지 고민해봤는데 도무지 방법을 모르겠더라구요?…
결국 두 개의 카드가 같은 요소를 참조하고 있기 때문에 발생되는 문제인 것 같아서 이런 저런 자료를 찾아보다가 깊은 복사까지 가게 됐어요,,,,
JSON.parse(JSON.stringify(obj))를 활용해서 깊은 복사를 통해 서로 다른 객체를 참조하도록 구현했고, 이 방법으로 문제를 해결하긴 했는데,, 이게 맞는 방법인지 잘 모르겠어요ㅠ
이 문제에 대한 리뷰 ,,,, (다른 부분에 대한 리뷰도 당연히) 언제나 환영입니당 부탁드려요ㅜ_ㅠ
🌈 구현 결과물
_1.mp4
→ 난이도 별로 카드 수 변경됨
_2.mp4
→ 정답 맞출 시, 애니메이션 적용/ 모든 카드를 찾았을 시, 모달 띄워짐/ reset 클릭 시, 카드 순서 변경됨