1. 문제 발생❓
"use client";
import { Champion } from "@/types/Champion";
import { ChampionRotation } from "@/types/ChampionRotation";
import { getChampionRotation } from "@/utils/rioApi";
import { getChampionList } from "@/utils/serverApi";
import { useEffect, useState } from "react";
function RotationPage() {
const [rotation, setRotation] = useState<ChampionRotation | null>(null);
const [champions, setChampions] = useState<Champion[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const [rotationData, championData] = await Promise.all([
getChampionRotation(),
getChampionList(),
]);
setRotation(rotationData);
setChampions(championData);
console.log("로테이션 데이터", rotationData);
console.log("챔피언 데이터", championData);
// key값에 맞는 챔피언 목록
const freeChampions: Champion[] =
rotation?.freeChampionIds.flatMap((id) =>
champions.filter((champion) => champion.key === id)
) ?? [];
console.log("프리!!!!!!", freeChampions);
} catch (error) {
console.error("Error fetching data", error);
setError("데이터를 불러오는 중 오류가 발생했습니다.");
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) return <div>로딩 중...</div>;
if (error) return <div>error: {error}</div>;
return <div>로테이션 페이지</div>;
}
export default RotationPage;
< 문제점 >
- 외부에서 rotationData, championData는 데이터를 잘 가져오지만, rotation에서 가져오는 id값과 champion에서 가져오는 key값이 일치하는 데이터만 뽑아서 새로운 freeChampions 배열을 만들어야하는데 freeChampions 배열이 타입이 맞지 않다고 오류가 뜨는 상황(Champion[] 타입에는 undefined가 허용되지 않음)
- console.log("로테이션 데이터", rotationData)와 console.log("챔피언 데이터", championData)까지는 잘 나오지만 console.log("프리!!!!!!!", freeChampions)는 콘솔에 출력이 안되는 상황
2. 원인 추론 🔎
- map 함수의 동작
- rotationData.freeChampionIds 배열의 각 요소에 대하여 함수를 실행
- 이 경우, 각 id에 대해 find 매서드를 실행
- find 매서드의 특징
- 조건에 맞는 첫 번째 요소를 반환
- 조건에 맞는 요소가 없으면 undefined를 반환
- 함수 동작 결과
- champion 배열에서 첫 번째 요소를 찾지 못해 발생한 undefined 값들의 혼합
- 타입 불일치
- freeChampions의 타입은 Champion[]로 선언됨
- 하지만 실제 결과는 Champion 또는 undefined 타입을 가지고 있는 배열
- 결론: map과 find의 조합으로 인해 undefined를 포함할 수 있는 배열이 생성되어 선언된 Champion[] 타입과 불일치가 발생하여 TypeScript 오류가 발생한 것 같다.
3. 해결 과정 📋
왜 find 매서드가 rotationData의 id값과 championData의 key 값이 일치하는 첫 번째 요소를 찾을 수 없는지를 알아내는 것이 가장 중요한 해결책이 될 것 같다.
- rotationData와 championData fetch애소 엔드 포인트를 활용해 응답값 확인해보기
- champion.key는 문자열(string) 타입
- id는 숫자(number) 타입
- 해결 시도
- "champion.key === String(id)"로 수정
- String()을 사용해서 숫자 id를 문자열로 변환해줌
// key값에 맞는 챔피언 목록
const freeChampions: Champion[] =
rotation?.freeChampionIds.map((id) =>
champions.find((champion) => champion.key == String(id))
) ?? [];
- filter 매서드 사용하여 undefined값 제거
- 또한, rotationData.freeChampionIds와 championData가 항상 완벽하게 일치한다고 보장할 수 없기에 안전 장치로 filter 매서드를 사용하여 undefined 값을 걸러내주었다.
// key값에 맞는 챔피언 목록
const freeChampionList: Champion[] = rotationData?.freeChampionIds
.map((id) =>
championData.find((champion) => champion.key === String(id))
)
.filter((champion): champion is Champion => champion !== undefined);
setFreeChampions(freeChampionList);
4. 결과 ❤🔥
- id를 (숫자 -> 문자열)로 변경해주어 find를 사용해 일치하는 요소를 찾을 수 있었다.
- 만약을 대비해 filter 사용으로 undefined값은 제거해 주어 타입 불일치 오류를 없앨 수 있다.
'개인과제' 카테고리의 다른 글
Riot API를 활용하여 리그 오브 레전드 정보 앱 만들기⭐︎ (5) | 2024.10.08 |
---|---|
리그오브레전드 정보앱(트러블 슈팅2🌟) (0) | 2024.10.01 |
MBTI 과제 마무리 (0) | 2024.09.11 |
MBTI test(트러블 슈팅3🌟) (0) | 2024.09.10 |
MBTI test(트러블 슈팅2🌟) (0) | 2024.09.10 |