Next.js Discord

Discord Forum

useSearchParams breaking change

Unanswered
Bonaparte's Gull posted this in #help-forum
Open in Discord
Bonaparte's GullOP
useSearchParams() should be wrapped in a suspense boundary at page "/location".

i'm getting this error when building. Everything was fine before. How is this not a breaking change?

I'm using useSearchParams() in a client component at the top of my tree. (inside a context provider), If i wrap the provider with a Suspense boundary my entire page won't render when js is disabled.

Wut! Am I missing something.

57 Replies

Bonaparte's GullOP
downgraded to next 14.0.4... no longer getting the build error
@Bonaparte's Gull > useSearchParams() should be wrapped in a suspense boundary at page "/location". i'm getting this error when building. Everything was fine before. How is this not a breaking change? I'm using `useSearchParams()` in a client component at the top of my tree. (inside a context provider), If i wrap the provider with a Suspense boundary my entire page won't render when js is disabled. Wut! Am I missing something.
That is not a breaking change. The previous behaviour was a (hidden) bug. If you inspect the previous deployments, you’ll see metadata and page content are not visible without JavaScript loaded. They added this error just to make it not a hidden footgun but an actual error message for a code bug.

How to fix? Only use useSearchParams in the part of the page that needs access to the search params (instead of the whole page), and put that part inside a Suspense boundary with a fallback being the loading state before the search params get initialised.
Bonaparte's GullOP
If you inspect the previous deployments, you’ll see metadata and page content are not visible without JavaScript loaded

hmm.. this doesn't seem to be the case... just testing now.. JS disabled, everything has loaded as expected.

with JS disabled, my client only search bar doesn't load, which is to be expected..
Is that so? Since it was introduced in v13, useSearchParams has always caused the part using it up to the nearest Suspense (whether implicit via loading.js or explicit) to be client-side rendered. That’s a known behaviour and footgun that has harmed many websites. I’ll check with real code tomorrow, but that’s just what useSearchParams is, for statically rendered pages.
Bonaparte's GullOP
Only use useSearchParams in the part of the page that needs access to the search param

I need access to searchParams from the root, i've got a search bar and filter component (in a layout) that need access to searchParams
I'm not using any suspense boundaries or loading.ts files
well.. one for the search bar, but that's because a library i'm using uses window so i can only render on the client
It’s late my time so I can’t check. Will check tomorrow if no one else helps you by then
@Bonaparte's Gull > Only use useSearchParams in the part of the page that needs access to the search param I need access to searchParams from the root, i've got a search bar and filter component (in a layout) that need access to searchParams
I would use parallel route for the search,
app/route/layout.tsx
app/route/@search/default.tsx
so you can access the searchParams object without the need of useSearchParams()
Bonaparte's GullOP
both the filter and search box need access to the context defined in my wrappers (ListingContext)
Bonaparte's GullOP
anyhow... everything works as expected in 14.0.4.
broken in 14.1.0
and the FilterBox
Bonaparte's GullOP
narp... i'm using useSearchParams in ListingContext
oh ok
Bonaparte's GullOP
i think it's pretty reasonable to call this a breaking change!
anyhow, thanks for your help
well it help preventing hidden bug
Bonaparte's GullOP
is this hidden bug documented anywhere?

the pages below /location are are both static and dynamic... there is a bunch of pages that will be generated at build time, but they also render based on query params

for example... /location/kent [static]
and location?lat=51.492314&lng=-0.263818&type=city&distance=3000&query=chiswick&sortBy=distance [dynamic]
Bonaparte's GullOP
waaaa! so confused... if this is a bug, how am I not seeing it!?
anyhow... thanks again for your help...
back to work!
Bonaparte's GullOP
back again... if using useSearchParams in 14.0.4 builds without failure, but breaks builds in 14.1.0, then surely this is a breaking change
@Multiflora rose seed chalcid
Bonaparte's GullOP
14.1.0
web:build: ⨯ useSearchParams() should be wrapped in a suspense boundary at page "/location". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
web:build:
web:build: Error occurred prerendering page "/location". Read more: https://nextjs.org/docs/messages/prerender-error

This build time error doesn't happen on 14.0.4
Bonaparte's GullOP
<rant>
after all the headaches with revalidatePath/Tag not working as documented, and now this, I'm really starting to lose faith in next/vercel,
</rant>

with apologies... i know we're all trying our best... but daaaaamn
next 14.1 catch this when building
downgrading doesn't solve the issue
Bonaparte's GullOP
just seems a bit mad... what is the reasoning behind this. we could SSR and use query from useRouter in the pages router.

downgrading doesn't solve the issue
this what scares me the most... it does for me, and my page works as i'd expect in 14.0.4
Bonaparte's GullOP
sorry, talking about useSearchParams
I had nightmares with revalidatePath/Tag not working a few weeks ago... TBH, i've kinda moved on and ignored it. If my client says data is invalid, i just jump into vercel and clear out the cache manually. Not ideal, but there aren't enough hours in the day, I'm a solo freelance developer working on multiple projects, there is only so much time i can spend on this. Thankfully I'm only working/supporting one next site using the app router
many next sites using the pages router.. and no complaints from me!
after looking his code, I found out he had some component with useSearchParams and didn't wrap with Suspense
Bonaparte's GullOP
shit the bed! are you saying useSearchParams and revalidatePath/Tag are related issues ?
and the page fallback to client side fetching/rendering
yeah it may cause issue to the data cache
Bonaparte's GullOP
but again, all my pages are SSR'd (see for yourself https://www.kinsail.co/location)
Bonaparte's GullOP
nuts! so an unrelated "hidden bug", using a different api/function, is the reason why revalidatePath/Tag isn't working
insert brain exploding gif!
Bonaparte's GullOP
by using useSearchParams without a Suspense block is the reason why revalidatePath/Tag isn't working.

one is about getting the search query from the URL, the other is about clearing caches
it's Friday... pint o'clock. that'll do for today
thanks again @Ray , i appreciate you taking the time to talk with me about this.
my brain still hurts mind!! :lolsob:
I don't know what is reason causing the cache doesn't work as expected either but some folk here I help with was having same issue and got fixed by wrapping the component with suspense
Bonaparte's GullOP
i'm less worried about that.... as i said, i can jump into the vercel dashboard and blow up the cache..
what i'm more concerned about is useSearchParams breaking builds in 14.1.0, but not in 14.0.4, and this "hidden" bug that I can't replicate
just makes the app router sound unstable/brittle as F
@Bonaparte's Gull 14.1.0 > web:build: ⨯ useSearchParams() should be wrapped in a suspense boundary at page "/location". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout > web:build: > web:build: Error occurred prerendering page "/location". Read more: https://nextjs.org/docs/messages/prerender-error This build time error doesn't happen on 14.0.4
this is the warning they got when build
Entire page /[lang]/terms deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /[lang]/terms
 âš  Entire page /[lang]/find-a-tutor deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /[lang]/find-a-tutor
 âš  Entire page /[lang] deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /[lang]
 âš  Entire page /[lang]/404 deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /[lang]/404
   Generating static pages (19/24) [=== ] 
Bonaparte's GullOP
what version of next is that?
14.0.4
Bonaparte's GullOP
bonkers... i don't see that error/warning at all...
anyhow... i'm off now... thanks again, have a great weekend
then you case may be different
ok later