React|Infinite Scrollの実装
23316 ワード
無限スクロール
無限スクロールは、ユーザがページの下部に到達したときにコンテンツをロードし続けるユーザエクスペリエンス(UX)である.無限スクロールを実現するために必要な技術は次のとおりです.
react-query
を使用して実施され、react-intersection-observer
を使用してページの下部の要素を観察する.[useInfiniteQuery]
React Queryは、応答からデータを取得、キャッシュ、更新するライブラリである
useInfiniteQuery
Hookを提供します.React Query公式ドキュメントによれば、次のパラメータと戻り値があります.
const {
fetchNextPage,
fetchPreviousPage,
hasNextPage,
hasPreviousPage,
isFetchingNextPage,
isFetchingPreviousPage,
...result
} = useInfiniteQuery(
queryKey,
({ pageParam = 1 }) => fetchPage(pageParam),
{
...options,
getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,
getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,
}
);
パラメータ
1.最初のパラメータ-queryKey
react-queryは、データをキャッシュするための
key
値です.開発者は任意に指定できます.
各ロードされたデータは、異なる
key
値を使用する必要があります.2.2番目の引数-fetch関数
({ pageParam = 1 }) => fetchPage(pageParam)
2番目の引数は、要求データを含むAPI関数の関数です.fetchPage
は、応答の値を返さなければならない.無限スクロールを実行する必要がある場合は、次の要求データを含むデータを返すことができます.
たとえば、現在1ページ目のデータを要求している場合は、結果値を戻り値とともにエクスポートして、次回2ページ目のデータを要求できます.
pageParam
は使用される値であり、初期ページを初期ページに設定することができる.要約すると、結果値とともに
nextPage
およびisLast
の情報を導出すれば、次の要求でそれらを使用することができる.const fetchPage = ({ pageParam = 0 }) => {
// API
const { data } = await getData({ startIndex: pageParam });
// 다음 요청시 사용할 nextPage와 isLast
return {
result: data,
nextPage: pageParam + 1,
isLast: data.isLast,
}
}
3.第3次買収-options
{
...options,
getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,
}
最後のパラメータはオプションとして他の機能を提供します.さらにデータを取得する場合、
getNextPAgeParam
は、第2のパラメータコールバック関数が返す値を取得するために使用することができる.したがって、上記の例で返されるオブジェクトはnextPage
を含み、lastPage.nextPage
として使用することができる.getNextPageParam
は、2番目の引数コールバック関数が呼び出されたときに引数として渡される1つの値のみを返さなければならない.undefined
を返すとfetchコールバックは呼び出されませんので、最後のpayであれば利用できます.戻り値
1.Next Pageコールバックの取得
この関数を呼び出すと、次のページからデータを要求できます.この場合、2番目の引数に渡されるコールバックは、次のページ情報をパラメータとして受信し、呼び出す.
2. isFetching
useQuery
のisLoading
とは異なり、isFetching
でロードされていると判断できます.3. data
data
は、各ページのデータをリスト形式でリストする.ページ固有のデータには、2番目のパラメータコールバックの戻り値が含まれます.上記コールバックが使用されている場合、
data
は以下のようになります.const data = {
pages: [
{
result,
nextPage,
isLast,
},
{
result,
nextPage,
isLast,
},
// ...
]
}
[useInView]
Intersection Observer APIは、デフォルトのJS仕様に含まれるAPIです.
React Intersection Observer
ライブラリを使用して、リトラクト中にIntersection Observer APIを使用します.ライブラリドキュメントは
useInView
Hookを提供し、以下に示す.import React from 'react';
import { useInView } from 'react-intersection-observer';
const Component = () => {
const [ref, inView] = useInView();
return (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
);
};
戻り値
1. ref
refを観察する要素に渡せばよい.
2. inView
boolean値.ビューポートに観察中の要素が表示されている場合は
true
、さらにfalse
を返します.[無限スクロールを実現]
上記の2つの技術を用いて無限スクロールを実現した.
戻り値で観察する要素(
ObservationComponent
)をコンテンツの一番下に追加すると、正常に動作します.ObservationComponent
が観察されると、inView
の値が変更されるので、useEffect
を使用してfetch関数が呼び出されます.import { ReactElement, useEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import { useInfiniteQuery } from 'react-query';
import { AnyObject } from 'immer/dist/internal';
import { DEFAULT_SEARCH_QUANTITY, SearchType } from '@type/web/event';
import { getEventList } from '@api/event/event';
interface UseInfiniteQueryWithScrollParamsTypes {
currentSearchType: SearchType;
queryString: AnyObject;
}
interface UseInfiniteQueryWithScrollReturnTypes {
data: any[] | undefined;
error: string | undefined | unknown;
isFetching: boolean;
ObservationComponent: () => ReactElement;
}
/**
* 사용 기술
* Recat query: useInfiniteQuery (https://react-query.tanstack.com/guides/infinite-queries)
* react-intersection-observer: useInView
*/
export default function useInfiniteQueryWithScroll({
currentSearchType,
queryString,
}: UseInfiniteQueryWithScrollParamsTypes): UseInfiniteQueryWithScrollReturnTypes {
const getEventListWithPageInfo = async ({ pageParam = 0 }) => {
const { data } = await getEventList({
...queryString,
eventType: currentSearchType,
searchType: currentSearchType,
startIndex: pageParam,
});
const nextPage =
data.length >= DEFAULT_SEARCH_QUANTITY ? pageParam + 1 : undefined;
return {
result: data,
nextPage,
isLast: !nextPage,
};
};
const { data, error, isFetching, fetchNextPage } = useInfiniteQuery(
[`eventListData-${currentSearchType}`],
getEventListWithPageInfo,
{
getNextPageParam: (lastPage) => lastPage.nextPage,
},
);
const ObservationComponent = (): ReactElement => {
const [ref, inView] = useInView();
useEffect(() => {
if (!data) return;
const pageLastIdx = data.pages.length - 1;
const isLast = data?.pages[pageLastIdx].isLast;
if (!isLast && inView) fetchNextPage();
}, [inView]);
return <div ref={ref} />;
};
return {
data: data?.pages,
error,
isFetching,
ObservationComponent,
};
}
Reference
この問題について(React|Infinite Scrollの実装), 我々は、より多くの情報をここで見つけました https://velog.io/@heelieben/React-Infinite-Scroll-구현하기-react-query-react-intersection-observerテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol