next-query-params icon indicating copy to clipboard operation
next-query-params copied to clipboard

[Nextjs 14.1] Missing Suspense boundary with useSearchParams

Open jrozbicki opened this issue 1 year ago • 6 comments

Describe the bug

Using Next.js 14.1, build throws errors for bunch of pages, one of which was:

 ⨯ useSearchParams() should be wrapped in a suspense boundary at page "/404". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout

Error occurred prerendering page "/_not-found". Read more: https://nextjs.org/docs/messages/prerender-error

I'm not using useSearchParams directly anywhere - that's why I came here.

Previous versions were throwing warning during build like:

Entire page /404 deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /404

But now it throws errors - stopping build.


Possible solutions

  1. wrap QueryParamProvider in Suspense like:
"use client";

import { Suspense } from "react";
import NextAdapterApp from "next-query-params/app";
import { QueryParamProvider } from "use-query-params";

function QueryParamsProvider({ children }: { children: React.ReactNode }) {
  return (
    <Suspense>
      <QueryParamProvider adapter={NextAdapterApp}>
        {children}
      </QueryParamProvider>
    </Suspense>
  );
}

export default QueryParamsProvider;

But, if we use it in root layout, it effectively will opt out from prerendering for all pages - works the same as with experimental flag they mention (which is discouraged).

If I took this custom QueryParamsProvider wrapper and put it as close to useQueryParam in the tree as possible (higher up the tree), it allowed 404 to be prerendered.

Not sure if this qualifies as bug, if this is fixable from library standpoint, it might just be tradeoff that you take into account then using it.

To Reproduce

Build any project using this library with Nextjs 14.1

Expected behavior

Build should pass.

jrozbicki avatar Feb 02 '24 12:02 jrozbicki

i have ran into the same issue stated here, wrapping the provider in a suspense as @jrozbicki mentioned did seem to resolve it but if its possible to fix it at the lib level that would be awesome

Jbenzs avatar Feb 25 '24 16:02 Jbenzs

But, if we use it in root layout, it effectively will opt out from prerendering

Why is this? I thought if you pass server components in as children, they will get prerendered along with whatever else is above the client query params context provider?

sgoodrow avatar Feb 26 '24 05:02 sgoodrow

@sgoodrow I think Suspense will show fallback until client side bundle is loaded with useSearchParams, maybe wrong tho...

https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout

jrozbicki avatar Feb 26 '24 07:02 jrozbicki

Yeah, it's a bit unfortunate that this library has to call useSearchParams in the provider, which generally means a rather top-level component in your app. That turned out to not work so well with more recent developments on the Next.js side. As long as this library is based on use-query-params, we're a bit limited here.

Maybe we could work with the folks at use-query-params to ask for a new adapter API based on our findings here or we'd have to go for a new direction without use-query-params (maybe only using the base library serialize-query-params) and implement the React-specific part ourselves.

Either way seems like a bigger topic. I recently came across another query params library for Next.js: nuqs. Their API seems to be a better fit for modern Next.js (including support for RSC), I'm honestly wondering if we should deprecate next-query-params in favour of nuqs.

I'm open to suggestions though in case someone has other ideas!

amannn avatar Feb 26 '24 08:02 amannn

Oh wow, nuqs looks fantastic.

sgoodrow avatar Feb 28 '24 03:02 sgoodrow

I tried nuqs and I think we should combine forces and help move it along. It's currently not sufficiently testable with RTL as it doesn't use the mock-next-router capabilities. I'll be using next-query-params until then.

sgoodrow avatar Mar 02 '24 07:03 sgoodrow