โ useInfiniteQuery ๊ฐ์ ธ์ค๊ธฐ
import InfiniteScroll from "react-infinite-scroller";
import { Person } from "./Person";
// ์ด ๋ถ๋ถ
import { useInfiniteQuery } from "react-query";
const initialUrl = "https://swapi.dev/api/people/";
const fetchUrl = async (url) => {
const response = await fetch(url);
return response.json();
};
export function InfinitePeople() {
// ์ปดํฌ๋ํธ์์ ํธ์ถ
const {data, fetchNextPage, hasNextPage} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam)
);
return <InfiniteScroll />;
}
- ๋ฐํ๋ ๊ฐ์ฒด์์ ํ์ํ๊ฑด data
- ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ๊ณ์ ๋ก๋ํ ๋ ์ฌ๊ธฐ์(data) ํ์ด์ง์ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ๊ฒ ์ ๋๋ค.
- fetchNextPage
- ๋ ๋ง์ ๋ฐ์ดํฐ๊ฐ ํ์ํ ๋ ์ด๋ ํจ์๋ฅผ ์คํํ ์ง๋ฅผ InfiniteScroll ์ ์ง์ํ๋ ์ญํ
- hasNextPage
- ์์งํ ๋ฐ์ดํฐ๊ฐ ๋ ์๋ ์ง๋ฅผ ๊ฒฐ์ ํ๋ boolean ์ ๋๋ค.
useInfiniteQuery ๋ ๋ช ๊ฐ์ง ์ธ์๋ฅผ ์ฌ์ฉํ๋๋ฐ โ
- ์ฟผ๋ฆฌ ํค ๋ก sw-people ์ ๋ ฅ
- ์ฟผ๋ฆฌ ํจ์({๋งค๊ฐ๋ณ์} => ํจ์(fetchUrl), {์ต์
})
- ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๊ณ ํ๋กํผํฐ ์ค ํ๋๋ก pageParam ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- pageParam ์ fetchNextPage ์ด ์ด๋ป๊ฒ ๋ณด์ผ์ง ๊ฒฐ์ ํ๊ณ , ๋ค์ ํ์ด์ง๊ฐ ์๋์ง ๊ฒฐ์ ํฉ๋๋ค.
- fetchUrl ์ด ํ๋ ์ผ์ Url์ธ pageParam ์ ๊ฐ์ ธ์์ json ์ผ๋ก ๋ฐํํด ์ค๋๋ค.
- useInfiniteQuery ๋ฅผ ์ฒ์ ์คํํ ๋๋ pageParam ์ ๊ธฐ๋ณธ๊ฐ์ ์ฃผ๋ฉด ๋ฉ๋๋ค.
- pageParam ์ด ์ค์ ๋์์ง ์๊ณ , ๊ธฐ๋ณธ ๊ฐ์ด ๋ฐ๋ก initialUrl(์์) ์ ๋๋ค.
โ getNextPageParam ์ต์
const {data, fetchNextPage, hasNextPage} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam : (lastPage) => lastPage.next || undefined
}
);
- getNextPageParam : (lastPage) => ์ฟผ๋ฆฌ ํจ์๋ฅผ ๋ง์ง๋ง์ผ๋ก ์คํํ ์์ ์ ๋ฐ์ดํฐ
- initialUrl ์ ๋ฐ์ดํฐ๋ next ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- next ํ๋กํผํฐ๋ ๋ค์ ํ์ด์ง๋ก ๊ฐ๋๋ฐ ํ์ํ Url ์ ์๋ ค์ค๋๋ค.
- fetchNextPage ๋ฅผ ์คํํ๋ฉด next ํ๋กํผํฐ๊ฐ ๋ฌด์์ธ์ง์ ๋ฐ๋ผ ๋ง์ง๋ง ํ์ด์ง์ ๋์ฐฉํ ๋ค์ pageParam ์ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
- hasNextPage ๋ lastPage.next ๊ฐ undefined ๋ฅผ ๋ฐํํ๋์ง ์๋์ง์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค.
โ React Infinite Scroller
Infinite Scroller ๊ฐ ์ข์ ์ ์ useInfiniteQuery ์ ํธํ์ด ์ ๋ฉ๋๋ค.
๋ฌดํ ์คํฌ๋กค ์ปดํฌ๋ํธ์ ํ๋กํผํฐ
- loadMore = {fetchNextPage}
- ๋ฐ์ดํฐ๊ฐ ๋ ํ์ํ ๋ ๋ถ๋ฌ์ useInfiniteQuery์์ ๋์จ fetchNextPage ํจ์ ๊ฐ์ ์ด์ฉ ํฉ๋๋ค.
- hasMore = {hasNextPage}
- useInfiniteQuery ์์ ๋์จ ๊ฐ์ฒด๋ฅผ ํด์ ํ ๊ฐ์ ์ด์ฉ ํฉ๋๋ค.
๋ฌดํ ์คํฌ๋กค ์ปดํฌ๋ํธ๋ ์ค์ค๋ก ํ์ด์ง์ ๋์ ๋๋ฌํ์์ ์ธ์ํ๊ณ fetchNextPage ๋ฅผ ๋ถ๋ฌ์ค๋ ๊ธฐ๋ฅ
- ๋ฐ์ดํฐ ํ๋กํผํฐ์์ ๋ฐ์ดํฐ์ ์ ๊ทผ ํ ์ ์๋๋ฐ useInfiniteQuery ์์ ๋์จ ๊ฐ์ฒด๋ฅผ ์ด์ฉ ํฉ๋๋ค
- ๋ฐฐ์ด์ธ ํ์ด์ง ํ๋กํผํฐ๋ฅผ ์ด์ฉํด์ ๊ทธ ํ์ด์ง ๋ฐฐ์ด์ map ์ ๋ง๋ค์ด ๋ฐ์ดํฐ๋ฅผ ํ์ ํ ์ ์๊ฒ ํด์ค๋๋ค.
์ฌ์ฉ
import InfiniteScroll from "react-infinite-scroller";
import { Person } from "./Person";
import { useInfiniteQuery } from "react-query";
const initialUrl = "https://swapi.dev/api/people/";
const fetchUrl = async (url) => {
const response = await fetch(url);
return response.json();
};
export function InfinitePeople() {
// TODO: get data for InfiniteScroll via React Query
// data ๋ useInfiniteQuery ์์ ๋ฐํ ๋ฉ๋๋ค.
const {data, fetchNextPage, hasNextPage} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam : (lastPage) => lastPage.next || undefined
}
);
return (
<InfiniteScroll loadMore={fetchNextPage} hasMore={hasNextPage}>
{data.pages.map(pageData => {
return pageData.results.map(person => {
return (<Person
key={person.name}
name={person.name}
hairColor={person.hair_color}
eyeColor={person.eye_color}
/>
)})
})}
</InfiniteScroll>
)
}
export function Person({ name, hairColor, eyeColor }) {
return (
<li>
{name}
<ul>
<li>hair: {hairColor}</li>
<li>eyes: {eyeColor}</li>
</ul>
</li>
);
}
- ์ ๋ฌ๋๋ ๋ฐ์ดํฐ ํ์
- ํ์ง๋ง ์์ ๊ฐ์ด ํ๋ฉด 'pages' ๊ฐ ์ ์๋์ง ์์๋ค๊ณ ์๋ฌ๊ฐ ๋ฐ์ ํฉ๋๋ค.
- useQuery ์ ๋ง์ฐฌ๊ฐ์ง๋ก isLoading ์ ์ฌ์ฉํด์ ์บ์์ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
import InfiniteScroll from "react-infinite-scroller";
import { Person } from "./Person";
import { useInfiniteQuery } from "react-query";
const initialUrl = "https://swapi.dev/api/people/";
const fetchUrl = async (url) => {
const response = await fetch(url);
return response.json();
};
export function InfinitePeople() {
// TODO: get data for InfiniteScroll via React Query
// data ๋ useInfiniteQuery ์์ ๋ฐํ ๋ฉ๋๋ค.
const {data, fetchNextPage, hasNextPage, isLoading, isError} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam : (lastPage) => lastPage.next || undefined
}
);
if (isLoading) {
return <div className="loading">Loading</div>
}
if (isError) {
return <div>Error !</div>
}
return (
<InfiniteScroll loadMore={fetchNextPage} hasMore={hasNextPage}>
{data.pages.map(pageData => {
return pageData.results.map(person => {
return (<Person
key={person.name}
name={person.name}
hairColor={person.hair_color}
eyeColor={person.eye_color}
/>
)})
})}
</InfiniteScroll>
)
}
๊ฒฐ๊ณผ
isFetching ์ ์ฌ์ฉํ๋ฉด โ
const {data, fetchNextPage, hasNextPage, isFetching, isError} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam : (lastPage) => lastPage.next || undefined
}
);
if (isFetching) {
return <div className="loading">Loading</div>
}
๋ฐ์ดํฐ๊ฐ ์์ง๋ง ์คํฌ๋กค์ด ๋งจ ์๋ก ์์์น๊ฐ ๋ฐ๋ณต ๋ฉ๋๋ค. ์ด์ ๋, ์๋ก์ด ํ์ด์ง๋ฅผ ์ด์ด์ผ ํ ๋ ์กฐ๊ธฐ ๋ฐํ์ด ์คํ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋ฌ๋ฉด ์ด๋ป๊ฒ โ
isFetching ์ ์กฐ๊ธฐ ๋ฐํ ์ํค์ง ์๊ณ , Loading ์ด๋ผ๋ ํ ์คํธ๋ฅผ ์ฐ์๋จ์ ์ถ๋ ฅํ๊ณ ์ถ๋ค.
import InfiniteScroll from "react-infinite-scroller";
import { Person } from "./Person";
import { useInfiniteQuery } from "react-query";
import React from "react";
const initialUrl = "https://swapi.dev/api/people/";
const fetchUrl = async (url) => {
const response = await fetch(url);
return response.json();
};
export function InfinitePeople() {
// TODO: get data for InfiniteScroll via React Query
// data ๋ useInfiniteQuery ์์ ๋ฐํ ๋ฉ๋๋ค.
const {data, fetchNextPage, hasNextPage, isLoading, isError, isFetching} = useInfiniteQuery(
"sw-people",
({ pageParam = initialUrl }) => fetchUrl(pageParam),
{
getNextPageParam : (lastPage) => lastPage.next || undefined
}
);
if (isLoading) {
return <div className="loading">Loading</div>
}
if (isError) {
return <div>Error !</div>
}
return (
<React.Fragment>
{isFetching && <div className="loading">Loading</div>}
<InfiniteScroll loadMore={fetchNextPage} hasMore={hasNextPage}>
{data.pages.map(pageData => {
return pageData.results.map(person => {
return (<Person
key={person.name}
name={person.name}
hairColor={person.hair_color}
eyeColor={person.eye_color}
/>
)})
})}
</InfiniteScroll>
</React.Fragment>
)
}
์ฐธ๊ณ
'๐ Front-End > React.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React + TypeScript(Optional Props) (0) | 2022.10.26 |
---|---|
React + TypeScript(interface) (0) | 2022.10.26 |
React Query - ๋ฌดํ ์คํฌ๋กค(Infinite Scroll) (0) | 2022.10.26 |
React Query - ๋ณ์ด(Mutation) (0) | 2022.10.25 |
React Query - isFetching VS. isLoading (0) | 2022.10.25 |