React-Query와 Suspense 사용해보기

hyeryeon·2024년 10월 19일

React

목록 보기
18/19

Suspense는 요소가 아직 로드 중이거나 아니면 이 자식에서 Suspense가 검출 됐을때 Fallback요소를 그려주는 역할을 한다.

<Suspense fallback ={<Loading />}>
  	<SomeComponent/>
</Suspense>

suspense는 뜻으로도 완성되지않은, 미완결된 인데 이름처럼
내부자식이 완결되지 않은, 로드되지 않았다면 fallback 요소를 그려줘면 된다.

지금 하고있는 프로젝트에서 메인페이지가 보여지기전에 로딩요소를 넣어줬는데 선언적이게 해보장

먼저,

React Query

  • 서버의 상태를 관리하는 라이브러리
  • 선언적으로 상태와 에러, 로딩 관리를 할 수 있다.
  • 캐싱, 값 업데이트 등 비동기과정을 편하게 사용가능

사용해보자~

import React from 'react'
import ReactDOM from 'react-dom/client'

import App from './App'
import { ModalContext } from './contexts/ModalContext'
import reportWebVitals from './reportWebVitals'
import './scss/global.scss'import { QueryClientProvider, QueryClient } from 'react-query'

const queryClient = new QueryClient()

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(
  <React.StrictMode><QueryClientProvider client={queryClient}>
   	 <ModalContext>
    	<App />
   	 </ModalContext>
    </QueryClientProvider>
  </React.StrictMode>,
)

reportWebVitals()

이렇게 index.ts에 추가해주면 내부에서 이 Queryclient에서 지원해준 값들을 사용할 수 있게된다

데이터패칭하는 hooks/useWedding.ts

import { Wedding } from '@models/wedding'
import { useState, useEffect } from 'react'

import { getWedding } from '../api/wedding'

function useWedding() {
  const [wedding, setWedding] = useState<Wedding | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(false)

  useEffect(() => {
    setLoading(true)

    getWedding()
      .then((response) => {
        if (response.ok === false) {
          throw new Error('청첩장 정보를 불러오지 못했습니다.')
        }

        return response.json()
      })
      .then((data) => {
        setWedding(data)
      })
      .catch((e) => {
        console.log('에러발생', e)
        setError(true)
      })
      .finally(() => {
        setLoading(false)
      })
  }, [])

  return { wedding, loading, error }
}

export default useWedding

지금은 로딩과 에러를 상태를 state로 관리하고있는데

useQuery를 사용해보면

const {data,isLoading,error} = useQuery<Wedding>(['wedding',()=> )

첫번째 값은 키값이라 wedding을 넣어줬고,
두번째 인자는 Fetcher함수라서 아래의 getwedding().부분을 넣어준다

import { Wedding } from '@models/wedding'
import { useQuery } from 'react-query'
import { getWedding } from '../api/wedding'

function useWedding() {const {data,isLoading,error} = useQuery<Wedding>(['wedding',()=> getWedding()
      .then((response) => {
        if (response.ok === false) {
          throw new Error('청첩장 정보를 불러오지 못했습니다.')
        }

        return response.json()
      })])



  return { wedding:data,isLoading, error }
}

export default useWedding

이렇게 되면 인자에 useQuery를 사용한 부분에서 data,isLoading,error을 빼올 수 있다.
app.tsx에서


function App() {
  const { wedding, isLoading, error } = useWedding()if (loading) {
    return <FullScreenMessage type="loading" />
  }

  if (error) {
    return <FullScreenMessage type="error" />
  }

  if (wedding == null) {
    return null
  }

  const {
    date,
    galleryImages,
    groom,
    bride,
    location,
    message: { intro, invitation },
  } = wedding

  return (

여기서 로딩 부분을 suspense 처리해주고 싶은데
index.tsx에서 App을 Suspense로 감싸주고

 <Suspense fallback={<FullScreenMessage type="loading"/>}>
          <App />
        </Suspense>

App이 로드되지 않은 상태에서 fallback을 보여주겠다는것을 알 숭있다.

그리고 위에서 useQuery적용해준 hooks/useWedding.ts에서
suspense를 추가해준다.

import { Wedding } from '@models/wedding'
import { useQuery } from 'react-query'
import { getWedding } from '../api/wedding'

function useWedding() {

  const {data,isLoading,error} = useQuery<Wedding>(['wedding',()=> getWedding()
      .then((response) => {
        if (response.ok === false) {
          throw new Error('청첩장 정보를 불러오지 못했습니다.')
        }

        return response.json()
      }),
    {
        ⭐suspense:true
    }])



  return { wedding:data,isLoading, error }
}

export default useWedding

0개의 댓글