React 부트캠프 TIL 13

정다롱·2024년 8월 13일

내일배움캠프 TIL

목록 보기
12/39

🥇파리 올림픽 메달 트래커 만들기


과제 진행 순서

  • vite 사용하여 React 프로젝트 생성
  • 예시페이지 참고하여 컴포넌트 계층 나누기
  • App.jsx 파일 내에서 InputBox, MedalBox 컴포넌트 분리하기
  • 임의 데이터 채워서 form, table 구조 짜고 css 수정하기
  • 동적으로 변하는 데이터가 무엇인지 파악하고 useState로 상태관리하기
  • InputBox, MedalBox로 state 전달하기(props)
  • 국가 추가, 업데이트, 삭제 로직 구현하기
  • InputBox, MedalBox 컴포넌트와 CSS 파일 분리하기
  • 국가 추가, 업데이트, 삭제 함수 커스텀 훅으로 분리하기



App.jsx

  • state, 커스텀 훅 불러오는 위치
  const [country, setCountry] = useState("");
  const [gold, setGold] = useState("");
  const [silver, setSilver] = useState("");
  const [bronze, setBronze] = useState("");

  const { medals, add, update, clickDel } = useMedalActions();
  • 변경된 상태를 newMedal이라는 객체로 생성함
  const newMedal = {
    country,
    gold: gold,
    silver: silver,
    bronze: bronze
  };
  • 큰 제목과 함께 InputBox, MedalBox 컴포넌트를 렌더링함
  return (
    <div className="mainBox">
      <h1>2024 파리 올림픽</h1>
      <InputBox 	//props로 넘겨주기!!
        country={country}
        setCountry={setCountry}
        gold={gold}
        setGold={setGold}
        silver={silver}
        setSilver={setSilver}
        bronze={bronze}
        setBronze={setBronze}
        onAdd={handleAdd}
        onUpdate={handleUpdate}
      />
      <MedalBox medals={medals} onDelete={clickDel} />
    </div>
  );

InputBox.jsx

  • App.jsx에서 전달받은 state를 props로 받아 각 인풋 필드에 onChange 이벤트와 setState 함수를 연결
  • 각 인풋창과 추가, 업데이트 버튼을 포함하는 폼을 리턴함
  return (
    <>
      <form className="inputBox">
        <div className="inputField">
          <label>국가명 </label>
          <input
            maxLength="11"
            type="text"
            value={country}
            onChange={(e) => setCountry(e.target.value)}
            placeholder="국가명 입력"
          />
        </div>
        <div className="inputField">
          <label>금메달 </label>
          <input type="number" value={gold}
          onChange={(e) => setGold(e.target.value)} placeholder="금메달 개수" />
        </div>
        <div className="inputField">
          <label>은메달 </label>
          <input type="number" value={silver} 
          onChange={(e) => setSilver(e.target.value)} placeholder="은메달 개수" />
        </div>
        <div className="inputField">
          <label>동메달 </label>
          <input type="number" value={bronze} 
          onChange={(e) => setBronze(e.target.value)} placeholder="동메달 개수" />
        </div>
        <div className="btnBox">
          <button type="button" onClick={onAdd}>
            국가추가
          </button>
          <button type="button" onClick={onUpdate}>
            업데이트
          </button>
        </div>
      </form>
    </>
  );

Medal.jsx

  • App.jsx에서 전달받은 medals 상태를 받아옴
function MedalBox({ medals, onDelete })
  • 실제로 데이터를 출력해주는 위치
  • 데이터가 없으면 안내문구를, 있으면 테이블을 리턴함
    return (
      <table>
        <thead className="category">
          <tr>
            <th>국가명</th>
            <th>금메달</th>
            <th>은메달</th>
            <th>동메달</th>
            <th>액션</th>
          </tr>
        </thead>
        <tbody>
          {medals.map((medal, index) => (
            <tr key={index}>
              <td>{medal.country}</td>
              <td>{medal.gold}</td>
              <td>{medal.silver}</td>
              <td>{medal.bronze}</td>
              <td>
                <button onClick={() => onDelete(medal.country)}>삭제</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    );

useMedalActions.jsx

  • 메달의 추가, 수정, 삭제를 관리하는 커스텀 훅
  • medals라는 새로운 상태를 만들어 App.jsx에서 전달받은 newMedal 객체를 추가, 수정, 삭제함
  const [medals, setMedals] = useState(initialMedals);

  const countries = medals.map((e) => e.country);
// 추가하는 코드
  const add = (newMedal) => {
  // 모든 값이 입력되었는지 확인 하나라도 비어있으면 emptyForm 실행되고 멈춤
    if (emptyForm(newMedal)) return;
    // 입력한 국가가 리스트에 있는지 확인
    countries.includes(newMedal.country)
    // 리스트에 있으면 안내창
      ? alert("해당 국가가 이미 존재합니다")
      // 리스트에 없으면 medals에 newMedal 추가 (금메달 내림차순)
      : setMedals((medal) => [...medal, newMedal].sort((a, b) => b.gold - a.gold));
  };

과제를 마치며...

그거 자바스크립트 배운지 얼마나 됐다고 지금까지 다 바닐라 js로 썼더니 리액트 구조가 이렇게 낯선 줄 상상도 못했다. jsx..? 이것 뭐예요? 상태로 눈만 깜박였다. 리액트 문서가 아니었다면 지금까지도 완성하지 못했을 내 과제...ㅜㅜ DOM이 그리워질줄은 상상도 못했다. 근데 확실히 쓰다보니 DOM보다 편한가? 싶다가도 구조가 너무 복잡해서 아닌것같다가도.. 아무튼 잘 모르겠다.

0개의 댓글