Next.js 13: Dynamically Displaying Loading States During Search Param Changes
Ever wished your Next.js 13 application could gracefully handle search parameter changes and display a loading indicator while fetching updated data? This article dives into how to implement a seamless loading UI experience when search parameters change, making your application more user-friendly and visually engaging.
The Scenario
Imagine you have a Next.js 13 application displaying a list of products based on a category
search parameter. When the user clicks on a different category, the URL updates with the new search parameter, and the product list should refresh. However, the user might experience a noticeable delay while the data is fetched, which can be frustrating.
Original Code (without loading UI):
"use client";
import { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
export default function ProductList() {
const [products, setProducts] = useState([]);
const [searchParams] = useSearchParams();
useEffect(() => {
const category = searchParams.get('category');
fetch(`/api/products?category=${category}`)
.then(res => res.json())
.then(data => setProducts(data))
.catch(error => console.error(error));
}, [searchParams]);
return (
<div>
<h1>Products</h1>
<ul>
{products.map(product => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</div>
);
}
This code fetches the product data based on the category
search parameter, but it lacks a visual indication of the loading process. Let's enhance it with a loading UI.
Adding a Loading UI
We'll introduce a isLoading
state to track whether the data is being fetched. We'll also display a loading spinner while isLoading
is true and the product list once the data is available.
Updated Code (with loading UI):
"use client";
import { useState, useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
export default function ProductList() {
const [products, setProducts] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [searchParams] = useSearchParams();
useEffect(() => {
setIsLoading(true); // Set isLoading to true when fetching
const category = searchParams.get('category');
fetch(`/api/products?category=${category}`)
.then(res => res.json())
.then(data => {
setProducts(data);
setIsLoading(false); // Set isLoading to false after data is fetched
})
.catch(error => console.error(error));
}, [searchParams]);
return (
<div>
<h1>Products</h1>
{isLoading ? (
<div>Loading...</div>
) : (
<ul>
{products.map(product => (
<li key={product.id}>{product.name}</li>
))}
</ul>
)}
</div>
);
}
This updated code displays "Loading..." while the data is fetched, providing a visual cue to the user that the application is processing their request.
Additional Considerations
- Custom Loading Indicators: Replace the simple "Loading..." message with a visually appealing loading spinner or animation for a more polished user experience.
- Error Handling: Implement error handling mechanisms to display appropriate messages if the data fetching fails.
- Data Caching: Consider caching the fetched data to improve performance and reduce the number of API requests.
- Debouncing: If the search parameter changes frequently, introduce a debouncing mechanism to avoid excessive API calls and ensure a smooth loading experience.
By incorporating a loading UI, you significantly improve the user experience, making your Next.js 13 application more responsive and engaging.