본문 바로가기

WINK-(Web & App)/React.js 스터디

[2023 React.js 스터디] 임혜진 #2주차 - 즐거운 수강신청 사이트 만들기~

반응형

React.js 스터디 2주차 과제는 수강신청시즌에 걸맞는 '즐거운 수강신청 사이트 만들기' .. ! 즐거웠..나

문제는 크게 3개로 이루어져 있다.

 

1. 작성된 useEffect 함수를 참고하여 정상적으로 남은 시간이 돌아가도록 작성하시오.

const timer = useRef(null);
const [time, setTime] = useState(10);

useEffect(() => {
    timer.current = setInterval(() => {
      console.log('1초마다 실행');
      setTime((time)=>(time-1))
    }, 1000);
    return () => clearInterval(timer.current);
  }, []);

  useEffect(() => {
    // time이 변할 때 마다 실행됨.
    if (time==0){
      clearInterval(timer.current);
    }
  }, [time]);
  • time에 초기값 10이 들어가있고 이는 수강신청까지 남은 시간을 의미한다.
    따라서 우리는 1초마다 time이 1만큼씩 줄어들게 하여 타이머 기능을 만들어주어야 한다.

  • 자바스크립트의 setInterval은 첫번째 인자로 실행할 코드를 담고 있는 함수를 받고, 두번째 인자로 지연 시간을 밀리초(ms) 단위로 받는다. 따라서 타이머 기능을 구현하기 위해서는 setInterval의 첫번째 인자에 time을 1만큼 감소하게 하는 코드를 넣으면 된다. 해당 부분에 Setter 함수를 넣어서 해결해주었다.

  • 하지만 time이 음수로 내려가면 안된다. 이를 위해 deps에 time을 넣은 useEffect 함수를 하나 더 이용할 수 있다.
    useEffect의 deps에 특정 값이 들어가 있다면 컴포넌트가 처음 마운트될 때 뿐만 아니라 그 특정값이 바뀔 때마다도 호출되기 때문이다. time이 변할 때마다 그 값이 0인지 체크하고 0이라면 clearInterval 함수를 호출한다.
    clearInterval 함수는 timer변수를 초기화하여 타이머를 종료할 수 있게 한다.

 

2. map함수를 이용하여 timetable에 담긴 과목이 아래 예시와 같은 수강신청 화면으로 렌더링되게 하시오.

{timetable.map(subject =>(
    <tr key = {subject.name}>
        <td>{subject.title}</td>
        <td>{subject.professor}</td>
        <td>{subject.time}</td>
        <td><button name={subject.title} onClick={handleRegister}>신청</button></td>
	</tr>
))}
  • {timetable.map(subject =>() )}
    동적인 배열을 렌더링하기 위해서 자바스크립트 배열의 내장함수 map()을 사용한다.

  • button태그에는 onClick 이벤트를 걸어 handleRegister이라는 함수가 호출되도록 한다. 
    이때 button태그의 name속성을 subject.title으로 두어 이벤트핸들러에서 사용할 수 있도록 하자. 3번에서 계속 . . .

  • 이때 key를 사용하지 않는다면, 렌더링은 정상적으로 되지만 배열항목에 대한 key가 없다는 경고를 받게 된다.
    key를 추가하면 리액트가 요소를 추적할 수 있게되어 배열의 항목이 업데이트되거나 제거되었을 때 전체목록이 아닌 해당 항목만 렌더링 되므로 훨씬 효율적이라고 한다.
    따라서 힌트에 주어졌듯이 key값으로 subject.name을 이용한다.

  • tr과 td태그는 table태그의 자식요소가 되는 태그로 표를 만들기 위해 사용되었다.

 

3. e.target.name을 이용하여 alert 함수를 이용해 "(과목명) 수강신청에 성공하였습니다!"가 출력되도록 하시오. (단, if-else구문 처리는 금지)

const handleRegister = (e) => {
    if (time > 0) {
      alert('아직 수강신청 시간이 되지 않았습니다.');
      return;
    }
    alert(e.target.name+' 과목은 수강인원이 초과되었습니다.');
  • 2번 문제의 코드에서 onClick이벤트가 발생하면 handleRegister함수가 호출된다.
    target은 이벤트가 일어날 객체를 의미하므로 여기서는 button이 된다.

  • 우리는 alert함수로 과목이름이 출력되도록 해야하고, 그 과목이름은 button태그에서 name 속성에 넣어주었다.
    따라서 e.target.name을 통해 해당 과목이름을 알맞게 출력할 수 있다. 

 

 

▷ 결과

수강신청시간이 되지 않은 상태에서 신청버튼을 눌렀을 때
수강신청시간에 따라 신청버튼을 눌렀을 때 뜨는 alert창

 

▷ 전체코드

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

export default function Week2() {
  const timetable = [
    {
      name: '0',
      title: '웹클라이언트컴퓨팅',
      professor: '김영만',
      time: '12:00 ~ 13:00',
    },
    {
      name: '1',
      title: '운영체제',
      professor: '황선태',
      time: '13:30 ~ 14:30',
    },
    {
      name: '2',
      title: '컴퓨터네트워크',
      professor: '이상환',
      time: '16:00 ~ 17:30',
    },
  ]
  const timer = useRef(null);
  const [time, setTime] = useState(10);

  // 아래 미리 작성된 useEffect 함수를 참고하여 정상적으로 남은 시간이 돌아가도록 작성하시오.
  useEffect(() => {
    timer.current = setInterval(() => {
      console.log('1초마다 실행');
      setTime((time)=>(time-1))
    }, 1000);
    return () => clearInterval(timer.current);
  }, []);

  useEffect(() => {
    // time이 변할 때 마다 실행됨.
    if (time==0){
      clearInterval(timer.current);
    }
  }, [time]);

  const handleRegister = (e) => {
    if (time > 0) {
      alert('아직 수강신청 시간이 되지 않았습니다.');
      return;
    }
    alert(e.target.name+' 과목은 수강인원이 초과되었습니다.');
    
    // e.target.name을 이용하여 alert 함수를 이용해 "(과목명) 수강신청에 성공하였습니다!" 가 출력되도록 하시오.
    // if (e.target.name === 'index') { // 단, 다음 코드처럼 if-else 구문으로 처리하지 마시오. (관련없는 예시 코드입니다.)
    //   // e.target.name === '0' 과 같은 코드로 제출하시면 혼냅니다...
    //   alert('알고리즘 과목은 수강인원이 초과되었습니다.');
    //   return;
    // }
  }

  return (
    <div style={{ padding: '20px' }}>
      <h1>장바구니</h1>
      <h2>수강신청까지 남은시간: {time} 초</h2>

      <table border={"1"}>
        <tbody>
          <tr>
            <td>강의명</td>
            <td>담당교수</td>
            <td>시간</td>
            <td>신청하기</td>
          </tr>
          {/* map 함수를 이용하여 timetable에 담긴 과목이 아래 예시와 같은 수강신청 화면으로 렌더링되게 하시오. */}
          {/* <tr> 태그에 key 값으로는 과목 내용에서 name으로 설정하시오. */}
              {timetable.map(subject =>(
                <tr key = {subject.name}>
                <td>{subject.title}</td>
                <td>{subject.professor}</td>
                <td>{subject.time}</td>
                <td><button name={subject.title} onClick={handleRegister}>신청</button></td>
                </tr>
              ))}
          {/* Hint! { timetable.map(subject => <tr key={subject.name}> ... */}
        </tbody>
      </table>
    </div>
  );
}

 

항상 눈높이 답변해주시는 윙크회장님께 감사를 보냅니다 7__0

 

반응형