๋ฐ์ดํฐ fetching ๋ผ์ด๋ธ๋ฌ๋ฆฌ
props๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ฐ์ดํฐ์ ์บ์ฑ์ด ๊ฐ๋ฅ
infinite ์ฟผ๋ฆฌ ์ ๊ณต
mutation์ ์ฌ์ฉํ์ฌ ์บ์๋ฅผ ์ง์ ๊ด๋ฆฌ
dev tool ์ ๊ณต
const reactQueryClient = new QueryClient ( {
defaultOptions : {
queries : {
staleTime : 5 * 1000 ,
}
}
} )
const MyApp : FC < AppProps > = ( { Component, pageProps } ) : AppProps ) => {
return (
< QueryClientProvider client = { reactQueryClient} >
< ReactQueryDevtools initialIsOpen = { false} / >
< Component { ...pageProps } / >
< / QueryClientProvider >
)
}
nextjs์์ react-query ์ฌ์ฉ์ _app.js ํ์ด์ง๋ฅผ QueryClientProvider๋ก ๊ฐ์ธ์ผ ํ๋ค
ReactQueryDevtools๋ก ๊ฐ์ธ๋ฉด dev tools์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค
๋ธ๋ผ์ฐ์ ์๋์ ๊ฝ ๋ชจ์์ด ์๊ธฐ๋ฉฐ ๋๋ฅด๋ฉด dev tools๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ์ ์ถ์ ๋ฐ ์บ์ฑ ์ฌ๋ถ์ ํ์ธ์ด ๊ฐ๋ฅํ๋ค
key์ ๊ฐ์ ๋ฐ๋ผ ์ด๋ ํ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋์ง ํ์ธ์ด ๊ฐ๋ฅํ๋ค
React-query์ 3๊ฐ์ง ์ฃผ์ ๊ธฐ๋ฅ
queries: ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ธฐ ์ํ ๊ธฐ๋ฅ
mutation: post/update/delete์ ์์ฒญ์ ์ํ ๊ธฐ๋ฅ
queries cache: ๋ฐ์ดํฐ ์บ์ฑ
staleTime: ๊ธฐ๋ณธ ์ฟผ๋ฆฌ๊ฐ stale ์ํ๊ฐ ๋๊ธฐ๊น์ง ์์๋๋ ์๊ฐ, default๋ ๋ฐ๋ก stale ์ํ๋ก ๋ณํจ
cacheTime: inactive ์ฟผ๋ฆฌ๊ฐ ์บ์์์๋ถํฐ ์ญ์ ๋๊ธฐ๊น์ง ์์๋๋ ์๊ฐ, default๋ 5๋ถ
inactive: ์บ์ฑ๋์ด ์๋ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ๋๊ณ ์์ง ์์ ๊ฒฝ์ฐ inactive ์ํ๊ฐ ๋๋ค -> ์บ์ ๋ฐ์ดํฐ์ ์ฌ์ฉ ์ฌ๋ถ ํ์ธ
stale: stale ์ํ๊ฐ ๋๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ๋ชปํ๋ฉฐ re-fetch๋ฅผ ํด์ผ ์ฌ์ฉ ํ ์ ์๋ค -> re-fetch์ ํ์ ์ฌ๋ถ ํ์ธ
// get request
const { isLoading, isError, error, data } : UseQueryResult < IPerson , Error > = useQuery < IPerson , Error , IPerson , string > (
'person' , // query key
async ( ) => {
const res = await fetch ( '/api/person' ) ;
return res . json ( ) ;
} , {
staleTime : 5 * 1000 ,
cacheTime,
select : ( person ) => person . name // ์ํ๋ person ๋ฐ์ดํฐ๋ง ์๋ต์ผ๋ก ๋๊ธธ ์ ์์, 3๋ฒ์งธ ํ์
์ string์ผ๋ก ๋ณ๊ฒฝํด์ค์ผ ํจ
// ๋ณดํต์ ์ค์ ํ์ง ์๊ณ default๋ก ์ฌ์ฉํจ
}
) ;
if ( isLoading ) {
return (
< div >
< p > Loading ...< / p >
< / div >
)
}
if ( isError ) return < p > Error is { error ?. message } < / p > ;
return (
< >
< p > { data ?. id} < / p >
< p > { data ?. name} < / p >
< p > { data ?. age} < / p >
< / >
)
query data์ 'person'๊ณผ ๊ฐ์ ํน๋ณํ key๋ฅผ ์ง์ ํ ์ ์๋ค( cache key)
์ฟผ๋ฆฌ๊ฐ ์คํ ๋ ๋ ๋ฐ์ดํฐ๊ฐ ๊ฐ์ ๊ฒฝ์ฐ ์บ์ฑ์ด ๋๋ฉฐ ๋ค๋ฅผ ๊ฒฝ์ฐ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค
์ฟผ๋ฆฌ key๋ string์ด ์๋ array๋ก๋ ๊ฐ๋ฅํ๋ค
dynamic page์ ๊ฐ ํ์ด์ง์์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋ ['todos', 5]์ด์ ๊ฐ์ด ์ค์ ์ด ๊ฐ๋ฅํ๋ค
page์ ์ ๊ทผ ํ ๋ ๋ง๋ค react-query๊ฐ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก fetch ํด์ค๋ค
์ฌ๋ฌ ํ์ด์ง๋ฅผ ๋ธ๋ผ์ฐ์ ์ ์ผ ๋์ ๊ฒฝ์ฐ ๋ค๋ฅธ ํ์ด์ง์ ์๋ค๊ฐ ํญ์ ๋๋ฌ ์ ์ํ๋ฉด re-fetch๋ฅผ ์๋์ผ๋ก ์คํํ๋ค
staleTime๊ณผ ๊ฐ์ ์ต์
์ ์ ์ญ์์ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ _app.js์์ ์ ์ํ QueryClient ๊ฐ์ฒด ์ธ์คํด์ค์์ ํ๋ผ๋ฏธํฐ ๊ฐ์ผ๋ก ๋ฃ์ผ๋ฉด ๋๋ค
const fetchPerson = async ( ) : Promise < IPerson > => {
const res = async fetch ( '/api/person' ) ;
// need to do this with fetch since doesn't automatically throw errors axios and graphql-request do
if ( res . ok ) { // 200 response
return res . json ( ) ;
}
throw new Error ( 'Network response not ok' ) ; // need to throw because react-query functions need to have error throw
}
const { isLoading, isError, error, data } : UseQueryResult < IPerson , Error > = useQuery < IPerson , Error , IPerson , string > (
'person' , // query key
fetchPerson
fetch๋ฅผ ์ ์ํ๋ ๋ถ๋ถ์ ๋ณดํต fetchPerson๊ณผ ๊ฐ์ด ํจ์๋ก ๋ฐ๋ก ์ ์ํ๋ค
fetch๋ฅผ ์ฌ์ฉํ์ง ์๊ณ axios๋ฅผ ์ฌ์ฉํ๋ฉด try / catch ๋ฌธ์ผ๋ก ์ ์๊ฐ ๊ฐ๋ฅํ๋ค
dynamic page์์์ react-query
const getPersonById = async ( id : string | string [ ] | undefined ) : Promis < IPerson > => {
if ( typeof id === 'string' ) {
const res = await fetch ( `/api/person/${ id } ` ) ;
if ( res . ok ) {
return res . json ( ) ;
}
throw new Error ( 'error fetching user with id' ) ;
}
throw new Error ( 'invalid id' ) ;
}
const PersonPage : FC = ( ) => {
const {
query : { id } ,
} = useRouter ( ) ;
const { isLoading, isError, error, data } = useQuery < IPerson , Error > ( [ 'person' , id ] , ( ) => getPersonById ( id ) , {
enabled : ! ! id , // enabled will stop a query from running, so will only call when id is available (dependent queries)
} ) ;
}
if ( isLoading ) {
return (
< div >
< p > Loading ...< / p >
< / div >
)
}
if ( isError ) return < p > Error is { error ?. message } < / p > ;
return (
< >
< p > { data ?. id} < / p >
< p > { data ?. name} < / p >
< p > { data ?. age} < / p >
< / >
)
react-query์ key๋ ๊ฐ ํ์ด์ง์์ ์์ ๋ง์ key๋ฅผ ๊ฐ์ง๋ค
ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋๊ธฐ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ ์ฝ๋ฐฑํจ์๋ก ๋๊ธด๋ค
enabled๊ฐ false์ผ ๊ฒฝ์ฐ react-query๊ฐ ๋์ํ์ง ์๋๋ค
ํ์ด์ง ์์ ์ปดํฌ๋ํธ๊ฐ ์๊ณ ํ์ด์ง์ ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ key๋ฅผ ๊ฐ์ง ๊ฒฝ์ฐ ์ฟผ๋ฆฌ๊ฐ 2๋ฒ ๋ถ๋ฆฌ์ด์ง๋ค. staleTime์ ์ค์ ํด ๋์ผ๋ฉด ์บ์ฑ ๋ ๊ฐ์ ์ฌ์ฉํ๋ฏ๋ก ํ ๋ฒ๋ง ๋ถ๋ฆฌ์ด์ง๋ค
retry ์ต์
์ด ์์ผ๋ฉฐ default๋ 3์ด๋ค. ์๋ฒ์ ํต์ ์ด ์คํจํ ๊ฒฝ์ฐ ๋ช ๋ฒ๊น์ง ์ฌ์๋๋ฅผ ํ ์ง ์ค์ ํ๋ ์ต์
์ด๋ค. retryTime์ผ๋ก ๋ช ์ด๋ง๋ค ์คํํ ์ง๋ ์ค์ ์ด ๊ฐ๋ฅํ๋ค
ํ ์ปดํฌ๋ํธ์์ react-query๋ฅผ ์ฌ๋ฌ๊ฐ ์ฌ์ฉ ํ ๊ฒฝ์ฐ ๋น๋๊ธฐ๋ก ๋์ํ๋ค
const id = useQuery ( getUserId ) ;
const { isLoading, isError, error, data } = useQuery < IPerson , Error > ( [ 'person' , id ] , ( ) => getPersonById ( id ) , {
enabled : ! ! id ,
} ) ;
depending query๋ ์ฟผ๋ฆฌ๋ฅผ ๋๊ธฐ์ ์ผ๋ก ๋์ํ๊ณ ์ถ์๋ ์ฌ์ฉํ๋ค. ์์ ๊ฐ์ด ์ค์ ํ๋ฉด ์ฒซ ๋ฒ์งธ useQuery ํ
์ด ์คํ๋๊ธฐ๊น์ง ๋ ๋ฒ์งธ ํ
์ ๋์ํ์ง ์๋๋ค
React tutorial
React query ์๋ฒ ์ํ ๊ด๋ฆฌ