vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.62k stars 26.82k forks source link

URLSearchParams does not survive serialization/deserialization when passed from a client to a Server Action #71078

Open Scrumplex opened 2 hours ago

Scrumplex commented 2 hours ago

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/exciting-meitner-zrdlrs

To Reproduce

  1. Write a Server Action that takes URLSearchParams
  2. Try to call it from a client component

Current vs. Expected behavior

When calling URLSearchParams#toString() in a Server Action, it yields a malformed output (foo,bar,next,js), instead of actual query/search params (foo=bar&next=js).

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 15.0.0-canary.182 // Latest available version is detected (15.0.0-canary.182).
  eslint-config-next: N/A
  react: 19.0.0-rc-2d16326d-20240930
  react-dom: 19.0.0-rc-2d16326d-20240930
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local)

Additional context

No response

Scrumplex commented 2 hours ago

It seems like it gets serialized into a two-dimensional array.

I.e. URLSearchParams { 'foo' => 'bar' } -> [ [ 'foo', 'bar' ] ]

Bader975 commented 1 hour ago

https://nextjs.org/docs/app/api-reference/functions/use-search-params i think you can configure it yourself $={search} and so on you find more example in docs @Scrumplex

Scrumplex commented 51 minutes ago

nextjs.org/docs/app/api-reference/functions/use-search-params i think you can configure it yourself $={search} and so on you find more example in docs @Scrumplex

I don't want to find out the current search params, but rather construct my own search params that I can then send off to an external API. The server action from my reproduction example just returns the string, but in my application the query params would be sent off to an API.

For example, I have a client component that provides auto-completion using a search endpoint of my external API and in order to call the API I would just call a Server Action using await searchThing(params/* : URLSearchParams /*) but doing so results in a malformed query string on the server action.