-
Notifications
You must be signed in to change notification settings - Fork 1
react hooks가 특정 조건에서 실행되면 안되는 이유 & useQuery에 query function 매개변수가 undefined일 수도 있을 때 어떻게 해결할까 ‐ 2024.11.18
import { useQuery } from '@tanstack/react-query';
import Chart from 'components/StocksDetail/Chart';
import Header from 'components/StocksDetail/Header';
import PriceSection from 'components/StocksDetail/PriceSection';
import TradeSection from 'components/StocksDetail/TradeSection';
import { useParams } from 'react-router-dom';
import { getStocksByCode } from 'service/stocks';
export default function StocksDetail() {
const params = useParams();
const { id } = params;
if (!id) return;
const { data, isLoading } = useQuery(['stocks', id], () =>
getStocksByCode(id),
);
if (isLoading) return;
if (!data) return;
return (
<div className='flex flex-col'>
<Header code={id} />
<div className='flex h-[500px]'>
<div className='flex min-w-[850px] flex-col'>
<Chart code={id} />
<PriceSection />
</div>
<TradeSection />
</div>
</div>
);
}
React Hook "useQuery" is called conditionally. React Hooks must be called in the exact same order in every component render.
에러 발생!!
리액트 훅 ‘useQuery’가 특정 조건에서만 실행되어서 생긴 에러다.
useQuery는 id가 undefined일 경우에는 실행되지 않기 때문이다.
왜 특정조건에 실행되면 안될까?
React는 Hook 호출의 순서를 보장해야 하므로 모든 렌더링에서 같은 순서로 호출되어야 한다!
예를 들어 useState, useEffect hooks 간에도 정해진 호출 순서가 있기 때문이다.
→ 즉, 결론은 이러한 문제 때문에 리액트 훅은 조건문들을 거치지 않게 가장 최상위에 선언해주어야 한다!
오케이 useQuery가 조건에 걸리지 않도록 위에 선언해보자
import { useQuery } from '@tanstack/react-query';
import Chart from 'components/StocksDetail/Chart';
import Header from 'components/StocksDetail/Header';
import PriceSection from 'components/StocksDetail/PriceSection';
import TradeSection from 'components/StocksDetail/TradeSection';
import { useParams } from 'react-router-dom';
import { getStocksByCode } from 'service/stocks';
export default function StocksDetail() {
const params = useParams();
const { id } = params;
const { data, isLoading } = useQuery(['stocks', id], () =>
getStocksByCode(id),
);
if (!id) return;
if (isLoading) return;
if (!data) return;
return (
<div className='flex flex-col'>
<Header code={id} />
<div className='flex h-[500px]'>
<div className='flex min-w-[850px] flex-col'>
<Chart code={id} />
<PriceSection />
</div>
<TradeSection />
</div>
</div>
);
}
Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'.
에러 발생
useQuery에서 실행하는 getStocksByCode 함수가 매개변수로 id를 받고 있고 id에 타입은 undefined일수도 있기 때문에 생긴 오류이다. 이걸 어떻게 해결할 수 있을까?
import { useQuery } from '@tanstack/react-query';
import Chart from 'components/StocksDetail/Chart';
import Header from 'components/StocksDetail/Header';
import PriceSection from 'components/StocksDetail/PriceSection';
import TradeSection from 'components/StocksDetail/TradeSection';
import { useParams } from 'react-router-dom';
import { getStocksByCode } from 'service/stocks';
export default function StocksDetail() {
const params = useParams();
const { id } = params;
const { data, isLoading } = useQuery(
['stocks', id],
() => getStocksByCode(id!),
{ enabled: !!id },
);
if (!id) {
return;
}
if (isLoading) return;
if (!data) return;
return (
<div className='flex flex-col'>
<Header code={id} />
<div className='flex h-[500px]'>
<div className='flex min-w-[850px] flex-col'>
<Chart code={id} />
<PriceSection />
</div>
<TradeSection />
</div>
</div>
);
}
리액트 쿼리 enabled 옵션을 활용해서 해결할 수 있다.
enabled
옵션은 무엇일까?
React Query의 enabled
옵션은 특정 조건이 충족될 때만 쿼리를 실행하도록 제어하는 데 사용된다.
enabled
는 boolean
값을 받으며, 쿼리가 실행 가능한지를 결정한다.
-
enabled: true
(기본값): 쿼리 즉시 실행. -
enabled: false
: 쿼리가 실행되지 않고,useQuery
는 초기 상태(isLoading: false
,data: undefined
, 등)를 유지
→ 즉 enabled !!id
로 id가 undefined일 경우 false로 변환해 값을 넣어주면서 쿼리를 실행하지 않도록 할 수 있다.
쿼리가 실행되었다는 것은 id가 무조건 존재함을 보장할 수 있기에getStocksByCode(id!)
처럼 **Non-Null Assertion Operator(!)**으로 id가 undefined가 아니라고 단언해도 괜찮다고 생각한다.
- [FE] 프론트엔드 기술스택
- [FE] 라이브러리 없이 차트 구현 이유
- [FE] Canvas API 사용방법
- [FE] 네비게이션 바 애니메이션 구현
- [FE] Socket.io 사용방법
- [FE] Tanstack Router에 대하여...
- [FE] Intl(Internationalization) API
- [FE] React Suspense 적용
- [FE] 한글 입력 방식의 유연성을 높인 검색 시스템 구현하기
- [BE] 백엔드 기술 스택
- [BE] SSE vs Socket.io
- [BE] Redis를 도입하게 된 계기
- [BE] ACG Rule을 활용한 Secure CI CD 파이프라인 구현
- [BE] Nginx 로드밸런싱을 통해 한국 투자 API 소켓 제한 극복
- [BE] 주가 지수 기능 개발 과정
- [BE] 매수 및 매도 기능 개발 과정
- [BE] 실시간 자산 조회 기능 개발 과정
- [BE] 단위 테스트
- [BE] redis를 이용한 한국투자 Open API 세션 관리
- [BE] 데이터베이스 인덱싱
- [FE] React에서의 DOM 요소 접근 (useRef vs getElementById)
- [FE] Outlet을 활용한 공통 레이아웃 관리
- [FE] react hooks가 특정 조건에서 실행되면 안되는 이유 & useQuery에 query function 매개변수가 undefined일 수도 있을 때 어떻게 해결할까
- [FE] cross‐domain 로컬 환경에서 cookie로 인증 처리하기 with vite proxy
- [FE] 크롬&사파리 Composition 차이
- [FE] useEffect 의존성 배열
- [BE] Naver Cloud Platform HTTPS 무응답 현상
- [BE] 한국투자 Open API에서 access token을 발급받지 못하는 문제
- [BE] 한국투자 Open API와 웹소켓 연결이 되지 않던 문제
- [BE] 한국투자 Open API 웹소켓 연결이 중단되는 문제
- [BE] 같은 주식 주문이 동시에 여러 번 체결되는 문제
- [BE] 한국투자 Open API Websocket 세션을 두 개에서 한 개로 변경하기
- [BE] Nginx 로드 밸런싱 중 Socket bad Request 발생하는 현상
- [BE] 매수/매도 체결 로직에 의해 redis pub/sub이 정상적으로 동작하지 않는 문제