1. 정렬
현재는 금메달갯수를 기준으로 정렬했는데, 사용자가 select태그의 option을 클릭한 값에 따라 정렬가능하게 구현하게씀!
먼저 구조부터 짰는데 이때 리액트에서 예상치 못한 오류가!
<select name="medal-filter" id="medalFilter">
<option value="gold" selected>
gold
</option>
...
</select>
option태그에 selected를 넣으면 아래와 같이 오류가 뜬다👻
오류내용에 해답이 있듯이 `defaultValue` or `value`을 쓰면 됨!
그래서 defaultValue로 바꾸면 에러해결💫
<option value="gold" defaultValue>
1-1. 정렬할 필터값들을 배열로 저장한다음 map으로 뿌리기
const filterList = ["gold", "silver", "bronze", "total"];
<select
name="medal-filter"
id="medalFilter"
onChange={handleSelect}
value={selected}
>
{filterList.map((item, i) => (
<option key={i} value={item}>
{item}
</option>
))}
</select>
1-2. 그리고 선택한 필터를 useState에 관리!
(초기값은 금메달 갯수로)
const [selected, setSelected] = useState("gold");
1-3. 이제 선택한 필터로 data를 정렬하기!
여기서 엄청 헤맸다,,,ㅠㅠㅠ 결국 gpt 힌트를 받음ㅠㅠㅠㅠ
*객체의 속성 접근 방법
- 점 표기법
- obj.key
- obj라는 객체에서 key라는 이름의 속성을 찾는 방법
- 속성 이름이 고정되어 있을 때 사용
- 대괄호 표기법
- obj["key"]
- obj라는 객체에서 key라는 이름의 속성을 찾는 방법으로, 키를 문자열로 주는 방법
- 동적으로 속성 이름을 지정할 때 사용
👻그렇다,,, 나는 점 표기법으로 하니까 작동이 안됐다ㅠㅠㅠ 이걸 몇십분동안 헤맴...ㅠㅠㅠㅠ
const sortedItems = [...medalItems].sort((a, b) => {
return b.selected - a.selected;
});
💫대괄호 표기법으로 바꾸니까 해결!! 그리고 중간에 return을 깜빡하고 안썻더니 또 구현이 안됨☠️
const sortedItems = [...medalItems].sort((a, b) => {
return b[selected] - a[selected];
});
3-2 useEffect로 위에 코드를 넣어주기
여기서 왜 useEffect 훅을 사용할까🤔
useEffect 없이 외부에서 setMedalItems를 호출하면 무한 루프가 발생!👻
=> setMedalItems를 호출하면 React가 컴포넌트를 다시 렌더링
=> 컴포넌트가 다시 렌더링되면 위의 코드가 다시 실행되고 setMedalItems가 호출
=> 이 과정이 계속 반복되면서 무한 루프가 발생☠️ ☠️ ☠️
useEffect(() => {
const sortedItems = [...medalItems].sort((a, b) => {
return b[selected] - a[selected];
});
setMedalItems(sortedItems);
}, [selected]); // selected가 변경될때마다 리랜더링!
2. 로컬 스토리지로 데이터 관리
2-1 로컬 스토리지에 저장
*localStorage에 저장할 key이름 : "medalData"
- localStorage.getItem으로 키값이 medalData인 데이터가 있으면 가져오고, 없으면 빈배열로 넣기
- JSON.parse로 객체 변환
- push로 사용자가 입력한 값을 맨뒤에 추가
- localStorage.setItem으로 key이름이 "medalData", value는 위에 데이터를 합친 medalData넣고
- JSON.stringify로 JSON형태로 로컬 스토리지에 저장
const handleSubmit = (e) => {
...
const medalData = JSON.parse(localStorage.getItem("medalData")) || [];
medalData.push(newItems);
localStorage.setItem("medalData", JSON.stringify(medalData));
}
2-2 로컬 스토리지에서 업데이트
- localStorage.getItem으로 키값이 medalData인 데이터를 가져오고
- JSON.parse로 객체로 변환
- 가져온 데이터를 map으로 돌리면서 사용자가 입력한 나라명과 저장된 나라명을 비교하여 이전 데이터를 spread연산자로 복사한후, 덮어씌우기
- 덮어씌운 데이터를 JSON.stringify로 JSON형태로 변환후
- localStorage.setItem으로 로컬스토리지에 저장
const updateItem = (item) => {
return item.country === inputValues.country
? {
...item,
...copyCalculateTotal,
}
: item;
};
const handleUpdate = () => {
...
let medalData = JSON.parse(localStorage.getItem("medalData"));
medalData = medalData.map(updateItem);
localStorage.setItem("medalData", JSON.stringify(medalData));
}
2-3 로컬 스토리지에서 삭제
- localStorage.getItem으로 key이름이 medalData인 데이터를 가져온후
- JSON.parse로 객체로 변환
- filter로 사용하여 id를 비교한후, 일치하지 않는 것만 가져와서
- JSON.stringify로 json으로 변환후
- localStorage.setItem으로 로컬 스토리지에 저장
const filterById = (items, id) => items.filter((t) => t.id !== id);
const handleDelete = (deleted) => {
...
let getData = JSON.parse(localStorage.getItem("medalData"));
getData = filterById(getData, deleted.id);
localStorage.setItem("medalData", JSON.stringify(getData));
};
2-4 로컬 스토리지에서 가져와서 뿌리기
useEffect로 사용하여 앱이 로드될때 로컬 스토리지에 저장된 데이터를 가져와서 데이터 저장한 useState함수인 setMedalItems에 넣기
useEffect(() => {
setMedalItems(JSON.parse(localStorage.getItem("medalData")) || []);
}, []);
🚫번외로 테일윈즈를 사용할때 클래스명이 길어지는 경우가 있는데, 이때 클래스들을 하나의 클래스에 apply해서 만들었다. 근데 이게 좋지 않은 방식임!! 공식 문서에서도 사용하지 말라함! (강민튜터님 감자해여🥔)
'프로젝트 > 올림픽 메달 집계 사이트(完)' 카테고리의 다른 글
[올림픽 메달 집계 사이트] 회고록 (4) | 2024.11.01 |
---|---|
[올림픽 메달 집계 사이트] 1. 입력창,데이터 뿌리기,삭제,중복x,업데이트 (0) | 2024.10.30 |