Ive tried wrapping my code in Suspense Tags but Im still getting the following error while building production build of my nextjs app.
⨯ useSearchParams() should be wrapped in a suspense boundary at page "/find/searchResults". Read more:
at a (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:6747)
at f (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:23270)
at h (/home/yash/nextjs-hireme/hireme/.next/server/app/find/searchResults/page.js:1:3734)
at nO (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:45959)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47734)
at nL (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:65533)
at nN (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:63164)
at n$ (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:46311)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47780)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:62515)
Error occurred prerendering page "/find/searchResults". Read more:
Export encountered an error on /find/searchResults/page: /find/searchResults, exiting the build.
⨯ Static worker exited with code: 1 and signal: null
Ive also tried reinstalling the dependencies but nothing works. This page displays the search results fetched by the search-services component. Here's my folder structure:
app/
├── components/
| ├── search-services.jsx
|
├── find/
│ ├── searchResults/
│ | ├── page.jsx
│ ├── page.jsx
Here's my code:
"use client";
import React, { useEffect, useState, Suspense } from "react";
import { useSearchParams } from "next/navigation";
import searchServices from "../../components/search-services";
import Link from "next/link";
import ServiceDetails from "../../components/service-details";
import { auth, db } from "../../firebase/config";
import { doc, getDoc } from "firebase/firestore";
import calculateDistance from "../../components/calculate-distance";
const SearchResults = () => {
const searchParams = useSearchParams();
const searchTerm = searchParams.get("query").trim() || "";
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(true);
const [selectedService, setSelectedService] = useState(null);
const [userLocation, setUserLocation] = useState(null);
const handleServiceClick = (service) => setSelectedService(service);
const handleCloseDetails = () => setSelectedService(null);
// Fetch user location from Firestore
useEffect(() => {
const fetchUserLocation = async () => {
auth.onAuthStateChanged(async (user) => {
if (user) {
const docRef = doc(db, "Users", user.uid);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const userData = docSnap.data();
if (userData.location) {
setUserLocation(userData.location); // Assume location is { latitude, longitude }
}
}
} else {
console.log("User is not logged in");
}
});
};
fetchUserLocation();
}, []);
// Fetch search results
useEffect(() => {
const fetchResults = async () => {
if (!searchTerm) return;
setLoading(true);
try {
const services = await searchServices(searchTerm);
setResults(services);
} catch (error) {
console.error("Error fetching search results:", error);
}
setLoading(false);
};
fetchResults();
}, [searchTerm]);
return (
<Suspense>
<div className="min-h-screen bg-gray-50 px-4 py-6">
<h1 className="text-2xl font-semibold mb-4">Search Results for "{searchTerm}"</h1>
<Link href="/find" className="text-teal-600 mt-4 inline-block">
← Back to Search
</Link>
{loading ? (
<p>Loading...</p>
) : results.length === 0 ? (
<p className="text-gray-500">No services found.</p>
) : (
<div className="grid grid-cols-1 gap-4">
{results.map((service) => {
const distance = userLocation && service.location
? calculateDistance(userLocation, service.location)
: null;
return (
<div key={service.id} className="relative p-4 border rounded-lg cursor-pointer hover:bg-gray-50 transition-colors shadow-sm" onClick={(e) => {
e.stopPropagation();
handleServiceClick(service);
}}>
<div className="flex justify-between items-center">
<h2 className="text-lg font-semibold text-gray-800">{service.title}</h2>
</div>
<p className="text-gray-600 mt-2 line-clamp-2">{service.description}</p>
<div className="mt-2">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-500">Provider: {service.providerName}</p>
<p className="text-sm text-gray-500">Phone: {service.providerPhone}</p>
<p className="text-sm text-gray-500">Email: {service.providerEmail}</p>
</div>
{distance !== null && (
<div className="text-right">
<span className="text-md font-bold text-blue-700">
{distance.toFixed(2)} km
</span>
</div>
)}
</div>
</div>
<div className="mt-4 flex justify-between items-center">
<p className="text-teal-600 font-bold mb-2">
₹{parseFloat(service.price.min).toFixed(2)} - ₹{parseFloat(service.price.max).toFixed(2)}
</p>
<span className="text-sm text-gray-500">{new Date(service.timestamp).toLocaleDateString('en-GB')}</span>
</div>
</div>
);
})}
</div>
)}
{/* Display selected service details */}
{selectedService && (
<ServiceDetails
key={selectedService.userId}
userId={selectedService.userId}
service={selectedService}
onClose={handleCloseDetails}
/>
)}
</div>
</Suspense>
);
};
export default SearchResults;
I am running Next.js 15.1.6
Ive tried wrapping my code in Suspense Tags but Im still getting the following error while building production build of my nextjs app.
⨯ useSearchParams() should be wrapped in a suspense boundary at page "/find/searchResults". Read more: https://nextjs./docs/messages/missing-suspense-with-csr-bailout
at a (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:6747)
at f (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:23270)
at h (/home/yash/nextjs-hireme/hireme/.next/server/app/find/searchResults/page.js:1:3734)
at nO (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:45959)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47734)
at nL (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:65533)
at nN (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:63164)
at n$ (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:46311)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47780)
at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:62515)
Error occurred prerendering page "/find/searchResults". Read more: https://nextjs./docs/messages/prerender-error
Export encountered an error on /find/searchResults/page: /find/searchResults, exiting the build.
⨯ Static worker exited with code: 1 and signal: null
Ive also tried reinstalling the dependencies but nothing works. This page displays the search results fetched by the search-services component. Here's my folder structure:
app/
├── components/
| ├── search-services.jsx
|
├── find/
│ ├── searchResults/
│ | ├── page.jsx
│ ├── page.jsx
Here's my code:
"use client";
import React, { useEffect, useState, Suspense } from "react";
import { useSearchParams } from "next/navigation";
import searchServices from "../../components/search-services";
import Link from "next/link";
import ServiceDetails from "../../components/service-details";
import { auth, db } from "../../firebase/config";
import { doc, getDoc } from "firebase/firestore";
import calculateDistance from "../../components/calculate-distance";
const SearchResults = () => {
const searchParams = useSearchParams();
const searchTerm = searchParams.get("query").trim() || "";
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(true);
const [selectedService, setSelectedService] = useState(null);
const [userLocation, setUserLocation] = useState(null);
const handleServiceClick = (service) => setSelectedService(service);
const handleCloseDetails = () => setSelectedService(null);
// Fetch user location from Firestore
useEffect(() => {
const fetchUserLocation = async () => {
auth.onAuthStateChanged(async (user) => {
if (user) {
const docRef = doc(db, "Users", user.uid);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const userData = docSnap.data();
if (userData.location) {
setUserLocation(userData.location); // Assume location is { latitude, longitude }
}
}
} else {
console.log("User is not logged in");
}
});
};
fetchUserLocation();
}, []);
// Fetch search results
useEffect(() => {
const fetchResults = async () => {
if (!searchTerm) return;
setLoading(true);
try {
const services = await searchServices(searchTerm);
setResults(services);
} catch (error) {
console.error("Error fetching search results:", error);
}
setLoading(false);
};
fetchResults();
}, [searchTerm]);
return (
<Suspense>
<div className="min-h-screen bg-gray-50 px-4 py-6">
<h1 className="text-2xl font-semibold mb-4">Search Results for "{searchTerm}"</h1>
<Link href="/find" className="text-teal-600 mt-4 inline-block">
← Back to Search
</Link>
{loading ? (
<p>Loading...</p>
) : results.length === 0 ? (
<p className="text-gray-500">No services found.</p>
) : (
<div className="grid grid-cols-1 gap-4">
{results.map((service) => {
const distance = userLocation && service.location
? calculateDistance(userLocation, service.location)
: null;
return (
<div key={service.id} className="relative p-4 border rounded-lg cursor-pointer hover:bg-gray-50 transition-colors shadow-sm" onClick={(e) => {
e.stopPropagation();
handleServiceClick(service);
}}>
<div className="flex justify-between items-center">
<h2 className="text-lg font-semibold text-gray-800">{service.title}</h2>
</div>
<p className="text-gray-600 mt-2 line-clamp-2">{service.description}</p>
<div className="mt-2">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-500">Provider: {service.providerName}</p>
<p className="text-sm text-gray-500">Phone: {service.providerPhone}</p>
<p className="text-sm text-gray-500">Email: {service.providerEmail}</p>
</div>
{distance !== null && (
<div className="text-right">
<span className="text-md font-bold text-blue-700">
{distance.toFixed(2)} km
</span>
</div>
)}
</div>
</div>
<div className="mt-4 flex justify-between items-center">
<p className="text-teal-600 font-bold mb-2">
₹{parseFloat(service.price.min).toFixed(2)} - ₹{parseFloat(service.price.max).toFixed(2)}
</p>
<span className="text-sm text-gray-500">{new Date(service.timestamp).toLocaleDateString('en-GB')}</span>
</div>
</div>
);
})}
</div>
)}
{/* Display selected service details */}
{selectedService && (
<ServiceDetails
key={selectedService.userId}
userId={selectedService.userId}
service={selectedService}
onClose={handleCloseDetails}
/>
)}
</div>
</Suspense>
);
};
export default SearchResults;
I am running Next.js 15.1.6
Share Improve this question asked Feb 1 at 18:09 Yash KumarYash Kumar 217 bronze badges 02 Answers
Reset to default 3I would not recommend rendering the whole page client side, but if you want to keep it this way you can do this:
app/
├── find/
│ ├── searchResults/
│ │ ├── layout.tsx
│ | ├── page.jsx
in the layout.tsx
you can use suspense component and wrap children prop inside:
import { Suspense } from "react";
export default function SRLayout({ children }: { children: React.ReactNode }) {
return (
<Suspense>
{children}
</Suspense>
)
}
This approach is not ideal since it beats the whole point of partial prerendering and server side rendering.
Solved it by by calling the SearchResults component inside the Page component and wrapping it in a Suspense block.
import { Suspense } from "react";
const searchResults = () => {
// code
}
const Page = () => {
return (
<Suspense>
<searchResults />
</Suspense>
)
}
export default Page