-
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주차 기본/심화/생각 과제 ] 🍚 점메추 🍚 #3
base: main
Are you sure you want to change the base?
Conversation
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.
여기 완전 내가 배울거 백만개... 많이 배워가! 완전 고생해따!!!!!!
{step === 4 ? ( | ||
<Button onClick={handleClickReStart}>다시하기</Button> | ||
) : ( | ||
<> | ||
<Button onClick={handlePrevStep}>이전으로</Button> | ||
<Button disabled={!isSelected} onClick={handleNextStep}> | ||
{step === 3 ? "결과보기" : "다음으로"} |
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.
step을 따로 나눠서 지정해준게 너무.. 좋은거 같다!!!!
나는 그냥 줄줄이 props를 전달해서 중간에 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 drilling 넘 시러ㅠㅠㅠ 헷갈ㄹㅕㅠㅠ
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 gap5rem = css` | ||
gap: 5rem; | ||
`; | ||
|
||
const gap3rem = css` | ||
gap: 3rem; | ||
`; | ||
|
||
const FlexColumnCenter = styled.div` | ||
${centerFelx} | ||
flex-direction: column; | ||
`; | ||
|
||
const FlexRowCenter = styled.div` | ||
${centerFelx} | ||
flex-direction: row; | ||
`; |
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.
계속 반복되는 부분을 피하기도 하고, 조금씩 변화하는 부분을 채울 수도 있으니까?
근데 저거 시작하기 전에 했어야 했는데 다 끝나고 하나씩 옮긴 거라 뭐,,, 여기선 그다지 실효성은 없는 것 같긴 하다ㅠ
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.
혹시 이 MainHeader.jsx
파일이 어떤 역할을 하는지 알려줄 수 있나아..?
위에 보니까 Header.jsx
는 또 따로 있어가지구..
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.
아 MainHeader가 그 질문 바뀌는 부분ㅇㅣ야! Header가 그냥 처음으로 이거 버튼 나오는 부분이구!!
function handleGotoFirstStep() { | ||
handleGotoFirstPage(); | ||
} |
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로 handleGotoFirstPage
를 받아왔는데 바로 사용이 불가능한거야?! 그래서 다시 함수를 만들어준건가??
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.
아니! 바로 사용 가능해!!!
저렇게 둔 이유는 막 크게는 없고 혹시 인자 넘길 일 있을까봐 그렇게 한 건데, 막상 다 끝나니깐 없네,,,? 바꿔도 되겠다!
import styled from "styled-components"; | ||
import ByRandomStart from "./ByRandomStart"; | ||
|
||
import { St } from "../../style/commonStyle"; |
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.
TwoButtonStyle
가 아닌St
요렇게 불러오는 이유가 뭐야?
나는 필요한 스타일 컴포넌트가 있으면 그냥 그 이름 그대로를 import 해왔는대 밑에 코드를 보다 보니까 St. TwoButtonStyle
요렇게 쓰는거 같아서..!
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.
하나의 객체 안에 선언을 해주었는데, import 구문에 여러개 스타일 컴포넌트들이 불려오는 게 너무 번잡하다고 느껴서,,?
function handleClick() { | ||
setIsByRandom((prev) => !prev); | ||
setIsFirstStep(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.
setIsByRandom
이 앞에서 선언만 되고 어떤 기능을 하지 않는지 정의되지 않았을 경우에, 다른 컴포넌트에서 props로 받아와 정의해서 사용할 수 있으니까 그런거겠지 ...? 나는 안되는 줄 알고 일단 사용되지 않더라도 일단 정의하고 props로 넘겨줬었거든..ㅜㅜ
handleStart={handleStart} | ||
/> | ||
)} | ||
{isByType && null} |
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.
혹시 이 코드는 왜 넣었는지 알려줄 수 있을까....? 어떤 역할인지 궁금해🥺
{step == 1 && ( | ||
<CategoryChoose | ||
step={step} | ||
category={category} | ||
setCategory={setCategory} | ||
isSelected={isSelected} | ||
setIsSelected={setIsSelected} | ||
/> | ||
)} | ||
{step == 2 && ( | ||
<TypeChoose | ||
step={step} | ||
type={type} | ||
setType={setType} | ||
isSelected={isSelected} | ||
setIsSelected={setIsSelected} | ||
/> | ||
)} | ||
{step === 3 && ( | ||
<HumanChoose | ||
step={step} | ||
isHuman={isHuman} | ||
setIsHuman={setIsHuman} | ||
isSelected={isSelected} | ||
setIsSelected={setIsSelected} | ||
/> | ||
)} | ||
{step === 4 && ( | ||
<ResultByType category={category} type={type} isHuman={isHuman} /> |
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.
step을 따로 주니까 요렇게 한 컴포넌트에서 props를 넘겨주는걸 볼 수 있네... 나도 리팩토링 할 때 이렇게 해야겠다!
{isHumanArray.map((ele) => { | ||
return ( | ||
<Button | ||
key={ele} | ||
onClick={() => handleButtonClick(ele)} | ||
active={isSelected === ele}> | ||
{ele} | ||
</Button> | ||
); | ||
})} |
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.
map 함수 써서 Button 요렇게 많이 만들 수 있구나.. 코드 완전 간결해보여!
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.
파일 하나하나 간결해서 너무 보기 좋았고 새로운 코드들 많이 배워갈 수 있어서 좋았어용 칭찬 밖에 없는 리뷰라 어뜩하지,,,, 🥹 고생했어 🖤
export default function ByRandomBtn(props) { | ||
const { | ||
isByType, | ||
setIsByRandom, | ||
isByRandom, | ||
handleStart, | ||
isStart, | ||
setIsFirstStep, | ||
} = 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 구조분해할당 나도 써먹어봐야겠어 🤠
const StartBtn = styled.button` | ||
${St.centerFelx} | ||
|
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.
centerFelx 요고 먼지 알려 줄 수 있나요?!
return ( | ||
<St.WrapperForThree> | ||
<MainHeader>카테고리를 골라봐!</MainHeader> |
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.
왕 이렇게 St로 한번에 import받고 할 수 있었네,, 쨩쨩!!!
<ImgWrapper key={pic.name} src={pic.pic} alt={pic.alt} /> | ||
<ImgName>{pic.name}</ImgName> |
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.
대체 텍스트 꼼꼼하당 최고 😎
<Wrapper> | ||
<MainHeader>오늘의 이모티콘은!!</MainHeader> | ||
<RandomResult /> | ||
<ReStartBtn onClick={handleClickReStart}>다시하기</ReStartBtn> | ||
</Wrapper> |
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.
컴포넌트 분리 진짜 머싯다 !! 여기도 그렇구 다 파일 하나하나 너무 간결하고 보기 조아 🥺
/* 미디어쿼리 적용 예정 */ | ||
/* font-size: 62.5%; */ | ||
|
||
/* @media (min-width: 1200px){ | ||
font-size: 62.5%; | ||
} */ | ||
@media (min-width: 1000px){ | ||
font-size: 70% | ||
} | ||
@media (min-width: 931px) and (max-width:999px){ | ||
font-size: 62.5%; | ||
} | ||
//Surface Pro 7 | ||
@media (min-width: 901px) and (max-width:930px){ | ||
font-size:62.5%; | ||
} | ||
// | ||
@media (min-width: 831px) and (max-width:900px){ | ||
font-size: 160%; | ||
} | ||
//iPad Air | ||
@media (min-width: 790px) and (max-width:830px){ | ||
font-size: 150%; | ||
} | ||
//iPad Mini | ||
@media (min-width: 750px) and (max-width:789px){ | ||
font-size: 145%; | ||
} | ||
@media (min-width: 600px) and (max-width:749px){ |
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 FONT({ weight, size, lineHeight, letterSpacing }) { | ||
return ` | ||
font-family: "Pretendard"; | ||
font-weight : ${weight}; | ||
font-size : ${size}rem; | ||
line-height : ${lineHeight}rem; | ||
letter-spacing : ${letterSpacing}rem; | ||
`; | ||
} | ||
|
||
const fonts = { | ||
neon: FONT({ weight: 900, size: 5.0, lineHeight: 2.6, letterSpacing: 0 }), | ||
|
||
title01: FONT({ weight: 700, size: 2.0, lineHeight: 2.6, letterSpacing: 0 }), | ||
title02: FONT({ weight: 500, size: 1.6, lineHeight: 2.0, letterSpacing: 0 }), | ||
|
||
body01: FONT({ weight: 700, size: 1.4, lineHeight: 1.6, letterSpacing: 0 }), | ||
body02: FONT({ weight: 500, size: 1.2, lineHeight: 1.6, letterSpacing: 0 }), | ||
body03: FONT({ weight: 400, size: 1.2, lineHeight: 1.6, letterSpacing: 0 }), | ||
body04: FONT({ weight: 500, size: 1.1, lineHeight: 1.4, letterSpacing: 0 }), | ||
body05: FONT({ weight: 400, size: 1.1, lineHeight: 1.4, letterSpacing: 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.
우와 이렇게 해서 여기 이렇게 해서 ${({ theme }) => theme.fonts.body02}; 요롷게 쓸 수 있었구나 대박 진짜 많이 배워가요
|
||
export default function Header(props) { | ||
const { isFirstStep, handleGotoFirstPage } = 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.
처음부터 export를 쓰고 컴포넌트를 만들 수 있구나! 신기하당
<HeaderWrapper> | ||
<HeaderTitle>이모티콘 추천해줄게</HeaderTitle> | ||
{!isFirstStep && ( | ||
<GotoFirst onClick={handleGotoFirstStep}>처음으로</GotoFirst> | ||
)} | ||
</HeaderWrapper> | ||
); |
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.
컴포넌트를 태그처럼 쓸 수도 있는거구나..
background-color: ${({ theme }) => theme.colors.main}; | ||
`; | ||
|
||
const HeaderTitle = styled.h1` | ||
${({ theme }) => theme.fonts.title01}; | ||
`; | ||
|
||
const GotoFirst = styled.button` | ||
${St.centerFelx} |
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.
style을 theme로 넣는건 무슨 차이가 있는걸까효,,?
<Wrapper> | ||
{!isStart ? <MainHeader>원하는 추천 방식을 골라줘!</MainHeader> : null} |
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.
!isStart가 false일때 null 값이면 빈페이지가 되는걸까요?
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.
<Wrapper> | |
{!isStart ? <MainHeader>원하는 추천 방식을 골라줘!</MainHeader> : null} | |
<Wrapper> | |
{!isStart && <MainHeader>원하는 추천 방식을 골라줘!</MainHeader>} |
요로코롬 하면 되겠당
@media (min-width: 471px) and (max-width:580px){ | ||
font-size: 93%; | ||
} | ||
// | ||
@media (min-width: 451px) and (max-width:470px){ | ||
font-size: 16px; | ||
} |
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.
오아 1주차 심화과제에 있던 반응형을 이렇게 만드는거였구나
늦어서 미안이슈.. |
<Wrapper> | ||
<Header | ||
isFirstStep={isFirstStep} | ||
setIsFirstStep={setIsFirstStep} |
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.
요 친구는 Header에서 받아오지 않는 것 같아용!
const gap5rem = css` | ||
gap: 5rem; | ||
`; | ||
|
||
const gap3rem = css` | ||
gap: 3rem; | ||
`; | ||
|
||
const FlexColumnCenter = styled.div` | ||
${centerFelx} | ||
flex-direction: column; | ||
`; | ||
|
||
const FlexRowCenter = styled.div` | ||
${centerFelx} | ||
flex-direction: row; | ||
`; |
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.
스타일은 정말 베이직하게 틀이 공통되는게 아니라면 오히려 불필요한 리소스를 들이는 것보다 그냥 직접 쓰는게 더 좋을 것 같아서 잘 고려해보면 좋을 것 같아용!
{!isFirstStep && ( | ||
<GotoFirst onClick={handleGotoFirstStep}>처음으로</GotoFirst> | ||
)} |
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.
아 깔꼼하당
<Wrapper> | ||
{!isStart ? <MainHeader>원하는 추천 방식을 골라줘!</MainHeader> : null} |
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.
<Wrapper> | |
{!isStart ? <MainHeader>원하는 추천 방식을 골라줘!</MainHeader> : null} | |
<Wrapper> | |
{!isStart && <MainHeader>원하는 추천 방식을 골라줘!</MainHeader>} |
요로코롬 하면 되겠당
<ByTypeBtn | ||
isByType={isByType} | ||
setIsByType={setIsByType} | ||
isByRandom={isByRandom} | ||
isStart={isStart} | ||
handleStart={handleStart} | ||
setIsFirstStep={setIsFirstStep} | ||
/> | ||
<ByRandomBtn | ||
isByRandom={isByRandom} | ||
setIsByRandom={setIsByRandom} | ||
isByType={isByType} | ||
isStart={isStart} | ||
handleStart={handleStart} | ||
setIsFirstStep={setIsFirstStep} | ||
/> |
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.
각 컴포넌트까지 살펴보았을 때, 두 버튼 컴포넌트가 각각 존재하는 것에 비해 로직이 분리되지 않고 있는 것 같아! 그래서 각 컴포넌트를 하나씩 만들지 말고, 하나의 컴포넌트로 만들어서 그 안에서 분기처리를 해주는 것이 더 적합하지 않을까 하는 생각입니당 :)
✨ 구현 기능 명세
🌱 기본 조건
🧩 기본 과제
[취향대로 추천]
답변 선택
이전으로, 다음으로(결과보기) 버튼
아무것도 선택되지 않았을 시 버튼을 비활성화 시킵니다.
→ 눌러도 아무 동작 X
→ 비활성화일 때 스타일을 다르게 처리합니다.
이전으로
버튼을 누르면 이전 단계로 이동합니다.다음으로
/결과보기
버튼을 누르면 다음 단계로 이동합니다.버튼 호버시 스타일 변화가 있습니다.
결과
[ 랜덤 추천 ]
[ 공통 ]
다시하기
버튼→ 랜덤추천이면
랜덤 추천 start
화면으로, 취향대로 추천이면취향대로 추천 start
화면으로 돌아갑니다.→ 모든 선택 기록은 리셋됩니다.
🌠 심화 과제
theme + Globalstyle 적용
애니메이션
헤더
처음으로
버튼→ 추천 종류 선택 화면일시 해당 버튼이 보이지 않습니다.
→ 처음 추천 종류 선택 화면으로 돌아갑니다.
→ 모든 선택 기록은 리셋됩니다.
[ 취향대로 추천 ]
단계 노출
이전으로 버튼
useReducer
,useMemo
,useCallback
을 사용하여 로직 및 성능을 최적화합니다.생각과제
💎 PR Point
기본 과제
1.a,b
=> 두 개의 컴포넌트를 나열했고, 각자 props를 내려 주었습니다.
=>
ByTypeBtn
컴포넌트의 경우,와 같게 Random을 선택하면 렌더링되지 않도록 설정하였습니다 (반대도 마찬가지 입니다!)
StartByType
은 취향대로 추천을 눌렀을 경우 나타나는 좀 커다란 컴포넌트입니다.[ 취향대로 추천 ]
2. a,b
=> styled-component 이용 (active가 클릭시 스타일 변화입니다)
=> 스타일을 다르게 처리했고, disabled로 비활성화 시켰습니다.
3.b 이전으로 버튼을 누르면 이전 단계로 이동합니다.
3. c 다음으로 / 결과보기 버튼을 누르면 다음 단계로 이동합니다.
=> 이전으로 누르면 이전 단계로 동작하는 부분을
useCallback
과useReducer
를 사용하여 구현하였습니다.3.d 코드 생략 (3.a와 비슷하게 구현)
5.a 결과
=> 결과를 걸러주는(?) 함수를 만들었습니다
=> useEffect를 이용해 카운트 다운 설정
=> 랜덤 결과 도출 함수
심화과제
1.a 코드 생략 (theme.js와 GlobalStyle.js )에서 확인하실 수 있습니다용
2.a
countDownAnimation.js
에서 확인가능3. a
=> 헤더에 가장 처음인지 아닌지를 알 수 있도록 하였고,
=> 처음이 아니면 처음으로 버튼이 보이도록 하였습니다.
4.a 코드 생략(step 부분을 props로 넘겨줘서 구현)
5.a 이전으로 버튼 (3.c 부분에 같이 나와 있습니다! 그 전 부분을 각 단계에서 저장하고, 이전 버튼을 누르면 그 부분을 불러와서 구현)
7.a (마찬가지로 3.c 부분에 나와있습니다)
🥺 소요 시간, 어려웠던 점
5h
🌈 구현 결과물
[ 취향 추천 + 다시 하기 - 기본(1-a,b/ 2-a,b/ 3-c,d/4-a/6-a) ]
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/302d311e-8e01-4b3e-aea9-23844afa33d9
[ 취향 추천 + 처음으로 + 심화(5.a, 3-a) ]
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/d7cb76ba-82c3-435e-a235-a021bf5d4ae3
[ 랜덤 추천 + 처음으로 ]
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/a5da5b79-d469-4d12-8a7f-0e5a11a9a37d
[ 랜덤 추천 + 다시 하기 - 기본(1-a,b/ 5.a,b/ 6.a) , 심화(2.a) ]
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/39707450-f918-4609-9109-07b3e3d0ae4c