
Suspense는 요소가 아직 로드 중이거나 아니면 이 자식에서 Suspense가 검출 됐을때 Fallback요소를 그려주는 역할을 한다.
<Suspense fallback ={<Loading />}>
<SomeComponent/>
</Suspense>
suspense는 뜻으로도 완성되지않은, 미완결된 인데 이름처럼
내부자식이 완결되지 않은, 로드되지 않았다면 fallback 요소를 그려줘면 된다.
지금 하고있는 프로젝트에서 메인페이지가 보여지기전에 로딩요소를 넣어줬는데 선언적이게 해보장
먼저,
사용해보자~
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