Open andrewgolovanov opened 1 year ago
I'm facing the same bug. In a page.tsx component with the route
my-app/roof/metal-roof?roofId=1&roofName=Metal&media=metal-232fcda5-d9c6-482d-b19d-c4b67071ef08.webp
I dynamically fetch data to generate metadata as follows:
export const dynamic = 'force-dynamic'
const baseUrl = process.env.NEXT_PUBLIC_URL
type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export async function generateMetadata(
{ searchParams }: Props,
parent: ResolvingMetadata,
): Promise<Metadata> {
console.log('πππ', searchParams)
}
In the development environment, I have the following console.log:
πππ { roofId: '1', roofName: 'Metal', media: 'vreeland-roof-metal-232fcda5-d9c6-482d-b19d-c4b67071ef08.webp' }
And after deploying on Vercel, I collect the log as follows:
πππ { roofName: 'Tile', media: 'vreeland-roof-tile-4aa17a43-b3b6-4df1-9f3e-2207abff0407.webp' }
The roofId
simply disappears. I read about the bug and added export const dynamic = 'force-dynamic'
, but still had no success. For client-side components, I gave up and went straight to useSearchParams
with useEffect
. But what about metadata that is generated on the server? How am I going to generate it dynamically? Why is the query parameter disappearing?"
Sorry for the slow reply here, but since this is a static page (e.g. using generateStaticParams
), you can't access properties of the incoming request like searchParams
. We should likely fail the build if this is detected. This is why you're seeing searchParams
be empty in this case.
@leerob It would awesome for the nextjs build to fail if we are using search params in a static page even when using force-static. Could it also be possible to display extra info when a page is being compiled in dev mode to know what Route Segment Config taken into account ? Thanks !
during "build, start" command locally it runs smoothly, but after "deploying" it to vercel "searchParams" is not detected in one route page but not in other, very strange!!
both is using "dynamic server" page but for "/articles/slug?id=1234" searchParams is getting undefined and for "/categories/some/slug?id=1234" its getting correct "searchParams" value!!
im using nextjs "14.0.4"
here is my code snippet for those two options
this snippet is failing after "deploying" but runs smoothly in local "build, start"
const ViewArticlePage = async ({params, searchParams}: {params: {id: string},searchParams: {id: string}}) => {
const ID = searchParams?.id
console.log(searchParams, "searchParams") // getting undefined
if(!ID) {
return (
<h2>Invalid ID -- {ID} {searchParams.id}</h2>
)
}
whereas this is fine and no error
const BlogArticlePage = async ({params, searchParams}: {params: {categoryId: string, articleId: string}, searchParams: {[key:string]: string}}) => {
const id = searchParams?.id
const articleData = await getArticleByCategory(params.categoryId, id)
const markups = <ViewFullArticleData {...articleData} />
return (
markups
)
}
any tips on why that might be?! they practically pointing to same "article slug" but from different routes, thanks for looking into this much appreciated, happy coding :)
during "build, start" command locally it runs smoothly, but after "deploying" it to vercel "searchParams" is not detected in one route page but not in other, very strange!!
both is using "dynamic server" page but for "/articles/slug?id=1234" searchParams is getting undefined and for "/categories/some/slug?id=1234" its getting correct "searchParams" value!!
im using nextjs "14.0.4"
here is my code snippet for those two options
- this snippet is failing after "deploying" but runs smoothly in local "build, start"
const ViewArticlePage = async ({params, searchParams}: {params: {id: string},searchParams: {id: string}}) => { const ID = searchParams?.id console.log(searchParams, "searchParams") // getting undefined if(!ID) { return ( <h2>Invalid ID -- {ID} {searchParams.id}</h2> ) }
whereas this is fine and no error
const BlogArticlePage = async ({params, searchParams}: {params: {categoryId: string, articleId: string}, searchParams: {[key:string]: string}}) => { const id = searchParams?.id const articleData = await getArticleByCategory(params.categoryId, id) const markups = <ViewFullArticleData {...articleData} /> return ( markups ) }
any tips on why that might be?! they practically pointing to same "article slug" but from different routes, thanks for looking into this much appreciated, happy coding :)
nevermind, i solved it, by making sure tht "dynamic route id" and "query params id" is not same....
i dont get it, if its going to be a problem after deployment why not make it so locally as well?!
happy coding :)
@bappyasif thank you so much, your comment solved my problem.
@yesh0907 glad you found that useful :)
happy coding :)
Make sure your params name is not the same as your searchParams name
Example: { params: { groupId: 'japanese' }, searchParams: {} } // Dont work because there's groupId in both params and searchParams
{ params: { groupName: 'japanese' }, searchParams: { groupId: 'edc7356e-3e4d-4c7d-b89b-a5b5978522df' } } // Work as expected
The proxy-based approach here for opting in to dynamic rendering doesn't really work in a lot of cases. Here's one I ran into:
"use client";
import { ToggleButton } from "@/app/button/ToggleButton";
export default function Page({ searchParams }: { searchParams: any }) {
return (
<ToggleButton onClick={() => doSomething(searchParams['parentOrigin'])} />
);
}
In this example I made "Page" a client component which uses an onClick
handler as the only place the searchParams is accessed. Since this handler is not executed on build, the proxy approach for detecting whether to use dynamic rendering doesn't work.
@ajwootto I have a similar case that your example. When we run yarn dev
, the search params are retrieved correctly. However, after generating a build and run yarn start
, the searchParams
object is populated only when we refresh/load the page, but after updating the params inside the application, for example, after filtering a table, the object is empty.
during "build, start" command locally it runs smoothly, but after "deploying" it to vercel "searchParams" is not detected in one route page but not in other, very strange!! both is using "dynamic server" page but for "/articles/slug?id=1234" searchParams is getting undefined and for "/categories/some/slug?id=1234" its getting correct "searchParams" value!! im using nextjs "14.0.4" here is my code snippet for those two options
- this snippet is failing after "deploying" but runs smoothly in local "build, start"
const ViewArticlePage = async ({params, searchParams}: {params: {id: string},searchParams: {id: string}}) => { const ID = searchParams?.id console.log(searchParams, "searchParams") // getting undefined if(!ID) { return ( <h2>Invalid ID -- {ID} {searchParams.id}</h2> ) }
whereas this is fine and no error
const BlogArticlePage = async ({params, searchParams}: {params: {categoryId: string, articleId: string}, searchParams: {[key:string]: string}}) => { const id = searchParams?.id const articleData = await getArticleByCategory(params.categoryId, id) const markups = <ViewFullArticleData {...articleData} /> return ( markups ) }
any tips on why that might be?! they practically pointing to same "article slug" but from different routes, thanks for looking into this much appreciated, happy coding :)
nevermind, i solved it, by making sure tht "dynamic route id" and "query params id" is not same....
i dont get it, if its going to be a problem after deployment why not make it so locally as well?!
happy coding :)
It works! You saved my life...
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
No response
Link to the code that reproduces this issue or a replay of the bug
https://github.com/andrewgolovanov/reproduction-app
To Reproduce
Steps for testing:
https://<your-vercel-domain>/user/1?test=1
searchParams
.https://<your-vercel-domain>/blog/1?test=1
searchParams
should be absent.Describe the Bug
The crux of the issue is that the
searchParams
object returns empty unless directly interacted with within the function body. For instance, passing it as a parameter for GraphQL operations results in an error due to its emptiness.Below is a snapshot from Vercel logs highlighting the problem:
For a more illustrative example, refer to this detailed use-case of searchParams. Here, utilizing
searchParams
becomes unfeasible as it's devoid of content.Similar closed issue [NEXT-601] search params object is empty in production with next 13 app dir where unfortunately the reproduction does not show the real problem
Related PR: It seems to me that the changes in this pull request are related to described issue
Expected Behavior
Developers should be able to rely on the
searchParams
object. It should consistently provide necessary query parameters without workarounds or dependency on a particular way it is utilized within the code.Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
Vercel
NEXT-1563