[Error] useQuery 사용 시 에러가 발생할 때 : A component suspended while responding to syncronous input. This will cuase...

profile
마릴린벅시
2022. 9. 22. 00:23프론트엔드

문제가 발생한 환경

  • next.js 사용
  • react 18 version
  • react-query 사용
  • 하나의 페이지에서 탭으로 여러개의 컴포넌트를 왔다갔다 하며 query가 실행될 때 에러 발생.

 


 

에러메세지

- A component suspended while responding to syncronous input. This will cuase...어쩌구

 

 


 

컴포넌트 모양과 에러 내용

  return (
    <ErrorBoundary FallbackComponent={<ErrorFallback />}>
      <Container>
        <TapMenu menu={menu} setMenu={setMenu} />
        {menu === 'MYPROFILE' ? (
          <MyProfile />
        ) : 
        menu === 'MYORDER' ? (
            <MyOrder />
        ) : null
        )}
      </Container>
    </ErrorBoundary>
  )

대략 이렇게 생긴 tap메뉴가 있는 화면에서, 현재 랜딩 된 tap 컴포넌트에서 다른 tap을 눌러 다른 컴포넌트를 렌더하면 위의 에러가 발생했다.

 


 

원인 : useQuery에서 suspense를 true로 줘 놓고 컴포넌트를 Suspense로 감싸지 않았음.

- useQuery의 옵션 중 react 18의 suspense기능을 사용하겠다는 옵션을 줄 수 있다. 

- 이것을 true로 줄 경우, 해당 useQuery를 호출하는 컴포넌트가 Suspense 컴포넌트로 감싸져있어야 한다.

- useQuery 코드

export const useGetProfile = (id: number, onSuccess: any) => {
  return useQuery(['myProfile', id], () => getMyProfile(id), {
    suspense: true, //==> true면, 해당 query를 호출하는 컴포넌트를 suspense로 감싸줘야 함
    retry: false,
    refetchOnWindowFocus: false,
    keepPreviousData: true,
    enabled: id !== null,
    onSuccess: (data) => onSuccess(data),
  })
}

 

해결

- react에서 제공하는 Suspense컴포넌트로 useQuery를 호출하고 있는 컴포넌트들을 감싸주었다.

- Suspense의 fallback props에는 무엇이든 useQuery가 process중일 때 보여줄 컴포넌트를 넣어주면 된다.

- useQuery에서 suspense옵션을 주지 않거나 false로 해두면 이러한 처리를 해주지 않아도 된다. 

- 하지만 suspense기능을 사용한다면 사용자에게 현재 데이터가 로딩중이라는 사실을 알려줄 수 있어 UX향상에 도움이 된다.

  return (
    <ErrorBoundary FallbackComponent={<ErrorFallback />}>
      <Container>
        <TapMenu menu={menu} setMenu={setMenu} />
        {menu === 'MYPROFILE' ? (
		<Suspense fallback={<Loading />}> {/* 요거 */}
         <MyProfile />
        </Suspense>
        ) : 
        menu === 'MYORDER' ? (
        <Suspense fallback={<Loading />}> {/* 요거 */}
         <MyOrder />
         </Suspense>
        ) : null
        )}
      </Container>
    </ErrorBoundary>
  )

 

이걸로 삽질 3시간 냠냠. 처음엔 랜덤하게 발생하는 에러인줄 알았다. (당연히 그럴 리가 없는데 행복회로를 돌렸던듯..)

에러가 발생한 코드 위치에는 문제의 소지가 없어보였고, 에러메시지는 무슨 뜻인지 이해 못함.

내가 저 옵션을 줘 놓고 Suspense 컴포넌트로 감싸는걸 까먹고 멀정한 코드 계속 수정해고 바꿔보고 

내가 queryKey를 잘못 줬나 수십번 확인하고 흑흑. 그래도 해결되니까 몇시간 삽질했는지는 중요치 않고 그냥 기분 좋음. 

이것이 개미지옥 개발의 매력.

 

 

 

반응형