Simplify Infinite Loading with React Query
source link: https://dev.to/brainiacneit/simplify-infinite-loading-with-react-query-48oj
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction
Fetching data in React applications can be a challenge, especially when it comes to infinite loading. React provides no built-in way to handle infinite loading, and it can be difficult to manage the state of data as it's being fetched.
Infinite loading is a common problem in web applications that display large amounts of data, such as social media feeds or product listings. Users expect these types of applications to load quickly and smoothly, even as more data is loaded.
Fortunately, there's a powerful library that can help simplify infinite loading in React applications: React Query. React Query provides a simple and efficient way to manage data fetching and caching in React applications, making it easier to handle infinite loading and improve the overall performance of your application.
Set up
We need react-query
, of course:
yarn add react-query
Then we need to use the provider, do this at your root file:
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</React.StrictMode>
The QueryClient
is created with const queryClient = new QueryClient();
. This creates a new instance of the QueryClient
that can be used to fetch and cache data.
The QueryClientProvider
is a component that allows the QueryClient
instance to be used throughout the application. The client
prop is used to pass the QueryClient
instance to the QueryClientProvider
.
Finally, the App
component is wrapped in the QueryClientProvider
, which makes the QueryClient
instance available to all of the child components of App
.
Observer
To determine when the browser should fetch new data, we require a certain logic. This involves triggering a callback whenever the user scrolls to a particular point on the page. Let's write a hook for this:
export default function useIntersectionObserver({
root,
target,
onIntersect,
threshold = 1.0,
rootMargin = "0px",
enabled = true,
}) {
React.useEffect(() => {
if (!enabled) {
return;
}
const observer = new IntersectionObserver(
(entries) =>
entries.forEach((entry) => entry.isIntersecting && onIntersect()),
{
root: root && root.current,
rootMargin,
threshold,
}
);
const el = target && target.current;
if (!el) {
return;
}
observer.observe(el);
return () => {
observer.unobserve(el);
};
}, [target.current, enabled]);
}
This code defines a custom hook named useIntersectionObserver
that's used to observe when a certain element intersects with another element, typically the viewport. The hook uses the IntersectionObserver
API to detect when the element becomes visible and triggers a callback function when it does.
The hook accepts an object as its argument with properties such as root
, target
, onIntersect
, threshold
, rootMargin
, and enabled
. These properties are used to configure the IntersectionObserver
.
The useEffect
hook is used to create and destroy the IntersectionObserver
when the component is mounted and unmounted respectively. It also watches for changes in the target.current
and enabled
properties, and only creates the observer if the enabled
flag is set to true.
The observer is created using the IntersectionObserver
constructor and is passed a callback function that is triggered whenever an intersection is detected. This function checks if the observed element (target.current
) is intersecting with another element, such as the viewport. If it is, the onIntersect
callback function is called.
The observer is then attached to the observed element using the observer.observe(el)
method, and the observer is removed from the observed element when the component is unmounted using the observer.unobserve(el)
method.
Implementation
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
} = useInfiniteQuery(
"starwars",
async ({ pageParam = "https://swapi.dev/api/people/" }) =>
await fetch(pageParam).then((res) => res.json()),
{
getNextPageParam: (lastPage) => lastPage.next ?? false,
}
);
const loadMoreButtonRef = React.useRef();
useIntersectionObserver({
target: loadMoreButtonRef,
onIntersect: fetchNextPage,
enabled: hasNextPage,
});
First I found an API in the internet to get Star Wars characters (lucky me ), okay let's breakdown the code
useInfiniteQuery Hook: The
useInfiniteQuery
hook from React Query is used to fetch and manage the data for the "starwars" query. It takes three arguments:- A query key (in this case, "starwars") to uniquely identify the query in the cache.
- An asynchronous function that fetches and returns the data. In this case, it fetches data from the SWAPI using the
fetch
function, with thepageParam
as the URL. IfpageParam
is not provided, it defaults to "https://swapi.dev/api/people/". - An options object containing the
getNextPageParam
function which determines the next page URL based on the response of the last page. It checks thenext
property of thelastPage
object and returns it if it exists, otherwise, it returnsfalse
.
The hook returns an object containing properties such as data
, fetchNextPage
, hasNextPage
, and isFetchingNextPage
.
React useRef Hook: The
React.useRef()
hook is used to create a mutable ref object (loadMoreButtonRef
) that can be passed as aref
attribute to a DOM element (e.g., a "Load More" button).useIntersectionObserver Custom Hook: This custom hook utilizes the Intersection Observer API to detect when the
loadMoreButtonRef
element comes into the viewport
Conclusion
In conclusion, infinite loading can be a challenging aspect to implement in React applications, but the React Query library simplifies the process by providing an efficient way to manage data fetching and caching. By utilizing custom hooks such as useIntersectionObserver
, developers can easily observe when an element comes into the viewport and trigger additional data fetching as needed. This allows for smooth and performant infinite loading experiences in web applications, meeting user expectations and improving the overall experience. With the help of React Query and a solid understanding of hooks, handling infinite loading in React applications becomes a much more manageable task.
Don't worry if this article is too obscure for you, check these out:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK