0. useParams undefined|string 반환
- useParams 는 undefined|string 을 반환한다.
- useParams 가 어째서 undefined를 반환하는지 궁금해졌다.
챗지피티 선생님께 여쭤봤다.
1) 매개변수가 경로에 없는 경우: 예를 들어, 경로가 /products/:productId로 정의되어 있지만 사용자가 /products만 방문한 경우, productId는 undefined가 됩니다.
2) 잘못된 경로 정의: 경로 정의를 잘못하여 매개변수를 포함하지 않는 경로에서 useParams를 호출하면, 해당 매개변수는 undefined가 됩니다.
3) TypeScript 타입 정의의 문제: useParams의 반환 타입을 정의하는 TypeScript 타입이 올바르게 설정되지 않았다면, 항상 값이 있어도 TypeScript에서는 undefined로 간주될 수 있습니다.
따라서 코드에서 useParams를 사용할 때는 항상 반환된 매개변수가 undefined인지 확인해야 합니다. 그렇지 않으면 예기치 않은 문제가 발생할 수 있습니다.
1. 해결과정
- 아래처럼 타입 네로잉을 해줬는데 eslint 에서 에러가 떴다.
const { productId } = useParams();
if (!productId) {
navigate("/*");
return null; // 혹은 적절한 대체 컴포넌트 렌더링
}
const { data } = useFetchProductDetail(productId);
const cartMutation = useMutation(cartAPI.createCart, {
onSuccess: () => {
console.log("성공");
},
onError: (error: any) => {
console.log(error);
},
});
const handlePostCart = async () => {
if (token) {
const cartData = {
token: token,
product_id: productId,
quantity: count,
check: true,
};
cartMutation.mutate(cartData);
navigate("/cart");
} else {
dispatch(openModal());
}
};
[eslint] src\Pages\ProductDetailPage\ProductDetailPage.tsx Line 28:20: React Hook "useFetchProductDetail" is called conditionally. React Hooks must be called in the exact same order in every component render react-hooks/rules-of-hooks Line 30:24: React Hook "useMutation" is called conditionally. React Hooks must be called in the exact same order in every component render react-hooks/rules-of-hooks Search for the keywords to learn more about each error.
해석 : React 훅은 컴포넌트의 렌더링 간에 호출 순서가 항상 동일해야 합니다. 조건문, 반복문, 중첩 함수 내에서 훅을 호출하면 호출 순서가 일관되지 않을 수 있습니다. 이러한 일관성의 결여는 예상치 못한 버그를 초래할 수 있습니다. 오류를 해결하기 위해서는 훅을 조건적으로 호출하지 않아야 합니다. 훅은 항상 컴포넌트의 최상위 레벨에서 호출되어야 합니다.
eslint 오류를 해결하기 위해 아래처럼 순서를 이동해주었다.
const { productId } = useParams();
const { data } = useFetchProductDetail(productId);
const cartMutation = useMutation(cartAPI.createCart, {
onSuccess: () => {
console.log("성공");
},
onError: (error: any) => {
console.log(error);
},
});
const handlePostCart = async () => {
if (token) {
const cartData = {
token: token,
product_id: productId,
quantity: count,
check: true,
};
cartMutation.mutate(cartData);
navigate("/cart");
} else {
dispatch(openModal());
}
};
if (!productId) {
navigate("/*");
return null; // 혹은 적절한 대체 컴포넌트 렌더링
}
하지만, 이러면 당연히 타입스크립트 에러가 뜰수밖에 없다. string|undefined에러가 해결되지 않기 때문이다.
2. 완전하지 않은 해결 : 타입단언 as , 기본값 설정
- 어쩔수 없이 as string 타입 단언을 해주었다. 위 두 에러를 모두 일으키지 않는 건 타입 단언이다. 하지만, as 를 쓰는 것은 타입스크립트를 쓰는 이유와 위배되는것이기 때문에 지양해야하는데, 편하다보니..쓸수밖에 없었다. 'as'키워드를 사용해서 강제로 타입 변환을 수행하면 타입 안정성을 손상시키기 때문에 as로 단언하기 보다는 undefined를 잘 네로잉 할 수 있어야 하는데..방법을 모르겠다.
- as 가 아니라 기본값을 설정해주었다. 사실 기본값 설정이나 as 나 별반 차이 없다고 생각한다. 어차피 둘다 강제하는 것이기 때문이다. 기본값이 실제로 의미가 없거나 잘못된 데이터를 가져올수 있기 때문이다.
- 하지만, 기본값이 url parameter로 갈경우 잘못된 경로이기 때문에 404페이지가 뜬다. as 보다는 미리 잘못된 타입을 막을 수 있어서 괜찮지 않을까 싶다.
const { productId } = useParams();
const productIdValue = productId || "defaultProductId";
const { data } = useFetchProductDetail(productIdValue);
const cartMutation = useMutation(cartAPI.createCart, {
onSuccess: () => {
console.log("성공");
},
onError: (error: any) => {
console.log(error);
},
});
const handlePostCart = async () => {
if (token) {
const cartData = {
token: token,
product_id: productIdValue,
quantity: count,
check: true,
};
cartMutation.mutate(cartData);
navigate("/cart");
} else {
dispatch(openModal());
}
};
'프로젝트 이모저모 > HoduMarket 프로젝트' 카테고리의 다른 글
오픈마켓 버그) 장바구니에 상품을 담을 경우 TotalPrice 컴포넌트 업데이트 안됨 (0) | 2023.08.18 |
---|---|
오픈마켓 프로젝트 버그) 최상단 훅 호출 불가, useQueries로 해결 (0) | 2023.08.11 |
오픈마켓 버그) 페이지네이션 다음 버튼 클릭하면 화면 렌더링 되지 않음 (0) | 2023.07.25 |
오픈마켓 프로젝트) createAsyncThunk 에서 React-Query로 리팩토링 (0) | 2023.07.18 |
오픈마켓 프로젝트) 토큰을 쿠키에 저장한 이유 (0) | 2023.05.23 |