[24.08.10] 개인 프로젝트 2일차 - 올림픽 메달 트래커

금메달 수 기준으로 내림차순 정렬하기

첫시도.. 아예 정렬이 되지 않음

{medalData.sort((a, b) => {
  return b.gold - a.gold;
}).map((data) => {
  return (
    <MedalTableRow key={data.country} data={data}></MedalTableRow>
  );
})}

 

그런데 입력창이랑 state를 연동해두다보니 입력창에 입력이 발생할 때마다 정렬을 하고있어서 아예 데이터를 추가/삭제할 때만 정렬할 수 있도록 함수로 빼기로 함

 

// 국가 추가/업데이트 버튼 컴포넌트
const sortData = (data) => {
  return data.sort((a, b) => b.gold - a.gold);
}

const updateButtonHandler = () => {
  let updatedMedalData = [];
  if (children === "업데이트") {
    const updateCountryData = medalData.find(
      (data) => data.country === medalDataInput.country
    );
    
    for (let key in medalDataInput) {
      updateCountryData[key] = medalDataInput[key];
    }
    
    updatedMedalData = [...medalData];
  } else {
    updatedMedalData = [...medalData, medalDataInput];
  }
  
  setMedalDataInput({});  // input field 비워주기
  
  updatedMedalData = sortData(updatedMedalData);
  setMedalData(updatedMedalData);
};

정렬하는 함수를 별도로 만ㄷ르어 state를 업데이트 해주기 전에 사용했다.

 

금, 은, 동 순으로 비교하기

sortData 함수에서 정렬 기준만 바꿔주었다.

const sortData = (data) => {
  return data.sort((a, b) => {
    if(+a.gold !== +b.gold) return b.gold - a.gold;
    else if(+a.silver !== +b.silver) return b.silver - a.silver;
    else return b.bronze - a.bronze;
  });
}

 

 

삭제 기능 만들기

const deleteRow = () => {
  let filteredData = medalData.filter(data => data.country !== country);
  setMedalData(filteredData);
}

삭제 버튼에 위 함수를 onClick 이벤트로 등록했다.

medalData state에서 삭제 버튼이 클릭된 row의 country이름과 같은 것을 필터링하고 업데이트 해준다.

 

0은 출력 안되는 버그 해결하기(onChange 이벤트 실행 안될 때)

0을 입력한 경우는 출력되지 않는다

 

00은 state에 추가되지만 silver, bronze에 입력한 0은 아예 state에 업데이트되고 있지 않다

 

어디가 문제인지 찾기위해 개발자도구에서 event.currentTarget.value를 받아오는 부분에 중단점을 찍어보았는데, 아예 0(기본으로 설정된 value)을 입력했을 때는 그 부분에 아예 들어오지 않음

00을 입력했을 때는 들어오는 것을 보아 0이라는게 문제가 아니라 onChange이벤트인데 기본값이 있으니 변화가 일어나지 않는다고 생각하는 것 같음

 

onChange 이벤트가 실행되지 않는 것이라는 추측이 생기니까, 메달 수가 0인 경우 사용자 입장에서는 0을 입력하는 것이 아니라 기본값 그대로 두고 국가 추가 버튼을 클릭할 수도 있을 것이라 생각이 들었다.

그래서 input field에서의 onChange 이벤트와 별개로 입력 값을 저장해두는 state에서 기본 값을 0으로 갖고있도록 설정해줬다.

0으로 입력했을 때도, 아무 입력을 하지 않았을 때도 0 이라고 잘 출력된다.

 

const inputHandler = (event) => {
  let input = { ...medalDataInput };
  input[`${dataType}`] = dataType === "country" ? event.currentTarget.value : +event.currentTarget.value;
  setMedalDataInput(input);
};

추가로 00, 03 과같이 출력되는 것을 방지하기 위해 country를 입력한 것이 아닌 경우 Number 타입으로 형변환하여 앞의 0을 없애주었다.

 

국가 추가를 눌러서 입력창의 값을 관리하는 state를 기본 상태로 만들어줘도, 다른 값들은 예상한 값으로 잘 돌아가는데 테스트 겸 00을 입력했던 필드는 변하지 않고 그대로였다.

기본 상태가 Number 0 이었는데, 아마 00은 숫자 0으로 인식해서 업데이트 처리를 하지 않는 거 아닐까? 하는 추측이 들었고 메달 수의 input field에 보이는 defaultValue를 Number -> String으로 변경해주었다.

// 변경 전
const defaultValue = dataType === "country" ? "" : 0;

// 변경 후
const defaultValue = dataType === "country" ? "" : "0";

 

아예 00이라는 입력이 되지 않고 0이라고 입력된다! -> 이걸 막는게 자연스러운건지는 잘 모르겠다..

 

 

국가명을 입력하지 않은 경우, 등록한 국가를 다시 추가하려는 경우

// 국가명을 입력하지 않은 경우
if(!medalDataInput.country) {
  alert("국가명을 입력해주세요.");
  return;
}

// 이미 등록한 국가를 추가하려는 경우
let isDuplicate = medalData.some(data => data.country === medalDataInput.country);
if(isDuplicate) {
  alert("이미 등록된 국가입니다.");
  return;
}

현재 등록되어있는 medalData state에 이미 국가명이 같은 객체가 있는지 확인하기위해 some을 사용했다!

달리기반에서 알려주셨던 걸 실제로 적용해봐서 뭔가 신기했다..

 

스타일 적용하기

야호