3주차 - 개인과제

정재연·2022년 1월 24일
4

개발일지

목록 보기
1/1
post-thumbnail

요일별 평점남기기

컴포넌트

1. App.js
2. Home.js
3. Detail.js
4. Evaluate.js

사용한 프레임

1. styled-components
2. react-router-dom

사용한 리엑트 훅

  1. useRef()
  2. useState()
  3. useEffect()

제일 처음 작업 한 것

  1. 페이지 만들기
  2. route 연결
  3. 컴포넌트 쪼개기
  4. console.log찍으면서 데이터 확인하기? ㅋㅋㅋ😎

1. useRef()

컴포넌트를 쪼갰을 때, 씨블링? 관계에서의 데이터 전달이 난감했다.
예를 들면 Home에 빨간 영역을 컴포넌트로 넣어 두었고,
요일을 map으로 돌렸다.

Detail페이지의 모습인데,빨간 영역에 사용자가 선택한 요일이 나와야 했다.즉,
Home에 있는 요일 중 수요일의 'go'버튼을 클릭하면,
Detail 페이지에는 수요일 평점 남기기가 나와야 한다.

이 문제를 해결 하기 위해 Dom 요소를 가져오는 useRef()을 App에 선언하고,
Home과 Detail 페이지를 연결해주었다.

Home에 'go'버튼을 누른 해당 요일을, ref로 보내주고, 그 값을 Detail 페이지로 넘겨 주었다.

2.useState()

별점을 남길 수 있는 Evaluate이라는 컴포넌트를 만들었다.
이 컴포넌트에서 추가해야할 동작은 2가지였다.
1. 사용자가 선택해서 나와야 하는 평점(Detail 용)
2. 랜덤으로 나와야 하는 평점(Home 용)

2-1 사용자가 선택해서 나와야 하는 별점(Detail 용)

useState로 변한 평점의 데이터값을 리엑트 돔에 알려주기 위해 사용했다.

우선 from을 사용하여 length가 5인 배열을 만들어 평점5개를 만들었다.

//Evaluate.js 컴포넌트
  const [evaluate, setEvaluate] = React.useState(-1);

  <StarWrap>
      {Array.from({ length: 5 }, (_, i) => {
        return (
          <Star
            isRandom={isRandom}
            key={i}
            onClick={() => {
              setEvaluate(i);
            }}
            className={i <= evaluate ? "active" : null}></Star>
        );
      })}
    </StarWrap>

evaluate 기본 셋팅값을 -1로 준 이유는
className에 i값이 evaluate보다 작거나 같을때 active(평점 컬러를 변경할 class명)를 리턴, 아님 null을 리턴해주도록 설정했다.

처음 Detail 페이지가 렌더링 될 때, 평점은 모두 회색이여야 한다.
만약, evaluate의 기본값이 0 이면 index로는 0은 별 하나를 의미하는 것이기 때문에 기본 셋팅이 별 1개로 나오도록 된다.

그렇다면 evaluate 기본값을 0으로 하고 className의 조건식을 <하나로 변경하면 안될까? 안된다.
렌더링 때는 원하는 데로 모두 회색으로 나오지만,
사용자가 클릭 했을 때, 선택한 개수 보다 하나 적게 리턴된다.(당연한 결과...)

i < evaluate ? "active" : null

evaluate의 기본값에 0을 주고 싶었지만, -1을 주는게 제일 깔끔했다. 👌🏻

➁ 별점들의 각 요소들을 index로 키값을 주었다.
클릭할때마다 index값을 받아서 setEvaluate()로 넘겨 주었다.

2-2 랜덤으로 나와야 하는 별점(Home 용)

사실 이 부분 때문에 고민을 좀 했다.
선택한 값이랑 랜덤으로 뿌려주는 값..... 혼란😵‍💫스러웠다.

우선,
isRandom에 Boolean 값을 각각 Home.js,Detail.js에서 props로 컴포넌트에 전달한다.

//Home.js 랜덤 평점
 <Evaluate isRandom={true}></Evaluate>
// Detail.js 사용자 평점 선택
<Evaluate isRandom={false}></Evaluate>

Evaluate 컴포넌트에서는 전달 받은 isRandom props 값이 true 이면, 0~4 까지의 랜덤 숫자를, 아니면 초기에 설정했던 -1값을 기본값으로 주었다.

// Evaluate 컴포넌트
  const randomNum = Math.floor(Math.random() * 5);
  const [evaluate, setEvaluate] = React.useState(isRandom ? randomNum : -1);

  return (
    <StarWrap>
      {Array.from({ length: 5 }, (_, i) => {
        return (
          <Star
            isRandom={isRandom}
            key={i}
            onClick={() => {
              setEvaluate(i);
            }}
            className={i <= evaluate ? "active" : null}></Star>
        );
      })}
    </StarWrap>
  );

3. useEffect()

Detail.js에서 숫자를 누르면 평점이 활성화 되도록 기능을 추가 했다.
키보드 2 눌렀을 때, 키보드 4 눌렀을 때,

useEffect 리액트 훅을 사용한 이유는 이벤트 리스너를 사용해야 했기 때문이다.
내가 사용한 이벤트는 keypress 였다.

// Evaluate 컴포넌트
 React.useEffect(() => {
   window.addEventListener("keypress", (e) => {
     if (e.key >= 1 && e.key <= 5) {
       setEvaluate(e.key - 1);
     }
   });
 }, [evaluate, isRandom]);
                                 

if문으로 1~5까지 키만 지정해 주었다.
setEvaluate에 index값으로 넣어 줘야 하기 때문에 -1을 해주어 전달했다.
Detail페이지에서는 잘 동작했지만 Home에서 똑같이 1키를 눌렀을때, 모든 요일의 평점이 1로 변경되고 에러가 떴다.

// Evaluate 컴포넌트
  const randomNum = Math.floor(Math.random() * 5);
  const [evaluate, setEvaluate] = React.useState(isRandom ? randomNum : -1);

  React.useEffect(() => {
    !isRandom &&
      window.addEventListener("keypress", (e) => {
        if (e.key >= 1 && e.key <= 5) {
          setEvaluate(e.key - 1);
        }
      });
  }, [evaluate, isRandom]);

  return (
    <StarWrap>
      {Array.from({ length: 5 }, (_, i) => {
        return (
          <Star
            isRandom={isRandom}
            key={i}
            onClick={() => {
              setEvaluate(i);
            }}
            className={i <= evaluate ? "active" : null}></Star>
        );
      })}
    </StarWrap>
  );

Evaluate 컴포넌트를 불러올때, Home Detail구분하기 위한 props isRandom를 사용하여, !isRandom 즉, Home이 아닐때에만 실행하도록 했다.
key enevts

4. 오늘부터 정렬하기


요일 중 오늘부터 정렬되도록!
이때, 알고리즘 문제를 풀때 사용했던
splice(),concat(),Date()를 사용했다.
우선 new Date()로 오늘의 요일을 index로 가져온다음,
만들어둔 요일 배열

//app.js
  let weekKoVersion = ["일", "월", "화", "수", "목", "금", "토"];

을 slice를 이용해 잘라 준다음 concat으로 잘라넨 요일을 뒤로 붙여 재배열 했다.

//app.js
 let weekKoVersion = ["일", "월", "화", "수", "목", "금", "토"];
 const today = new Date().getDay();
 let passDay = weekKoVersion.splice(0, today);
 weekKoVersion = weekKoVersion.concat(passDay);

weekKoVersion를 map으로 돌려주면 잘 나온다.

개인작업을 마친뒤 느낀점

평점 남기기 부분을 컴포넌트로 쪼갰는데, 이부분이 잘 할 것인지
고민이 좀 되었다.
고민이 되었던 부분은 Home에서 랜덤으로 나오는 별점 영역과
Detail 페이지의 별점을 같은 컴포넌트 하나로 사용했다.
그러면서 랜덤으로 뿌려져야 하는 별점 갯수와 사용자가 클릭해서 평가를해야하는 동작이 하나의 컴포넌트에서 이뤄져야 했다.
지금 상황에서 최선을 대한것이라 왕 뿌듯하다.

깃헙 주소

profile
코린이 개발자 :)

0개의 댓글