Server-side Data Fetching with Next.js and Lazy Load
Implement lazy loading data from the server-side in a Next.js app when a certain UI element is in view or an action is taken.
import { useState } from 'react';
import useSWR from 'swr';
// Function to fetch data (could be any async API call)
const fetchData = async (url) => {
const response = await fetch(url);
return response.json();
};
Define a fetchData function to make an API call and utilize useSWR hook for data fetching and caching.
import { useEffect, useRef, useState } from 'react';
const LazyLoadComponent = () => {
// State to store our data
const [data, setData] = useState(null);
// State to track if we should load the data
const [load, setLoad] = useState(false);
// Ref for the element we want to watch
const elementRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
// Check if element is in view
if (entries[0].isIntersecting) {
setLoad(true);
}
},
{ threshold: 0.1 }
);
// Start observing the element
if (elementRef.current) {
observer.observe(elementRef.current);
}
// Clean up observer on component unmount
return () => observer.disconnect();
}, []);
LazyLoadComponent uses an IntersectionObserver to check if the component's ref (elementRef) is in view. If so, it sets 'load' state to true.
const { data: serverData, error } = useSWR(load ? '/api/data' : null, fetchData);
useEffect(() => {
if (serverData) {
setData(serverData);
}
}, [serverData]);
Use the useSWR hook with the 'load' state to manage when to fetch the data. If 'load' is true, the API call is made; otherwise, it is skipped.
return (
<div>
{error && <div>Failed to load data.</div>}
{!data && <div ref={elementRef}>Loading...</div>}
{data && (
// Render your data here
<div>{JSON.stringify(data, null, 2)}</div>
)}
</div>
);
};
export default LazyLoadComponent;
Render the LazyLoadComponent, showing a 'Loading...' message until the data is fetched, upon which the data is rendered.