vercel / next.js

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

[ServerActions] Tagging function with "use server" doesn't work for class type dependencies / libs #50309

Closed Rodrigo-JM closed 1 year ago

Rodrigo-JM commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.3.0: Mon Jan 30 20:39:35 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T8103
    Binaries:
      Node: 18.15.0
      npm: 9.5.0
      Yarn: 1.22.19
      pnpm: 7.9.5
    Relevant packages:
      next: 13.4.4-canary.9
      eslint-config-next: 13.4.3
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.0.4

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue or a replay of the bug

https://github.com/Rodrigo-JM/bug-report-next-class

To Reproduce

-- > npm run dev

-- > http://localhost:3000

-- > Should break

Describe the Bug

Basically terminal outputs this, but i have clearly marked the function with "use server".

- error Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
  [function]
   ^^^^^^^^
    at stringify (<anonymous>)

import { ApiService } from "@/services";
import GetPokemon from "./(components)/(GetPokemon)";

export default async function Home() {
  const client = new ApiService("token here");

  const getPokemon = async (poke: string) => {
    "use server";
    const data = await client.getPokemonDetails(poke);
    console.log(data);
  };
  return (
    <main className={styles.main}>
      Bug Report <GetPokemon getPokemon={getPokemon} />
    </main>
  );
}

Expected Behavior

I have already figured it out how to "solve" this issue. I had to transform my api service out of the class structure and into separate functions. Each request should then be exported out of the file.

My expected behavior is just having to tag the "outer most" function of a given implementation, otherwise we could run into issues regarding dependencies / libs that leverage classes (which are still very useful!)

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

shuding commented 1 year ago

Yep the problem here is that you can't use the client instance inside your action function. We will make this message more clear in the future:

  const client = new ApiService("token here");
        ^^^^^^

  const getPokemon = async (poke: string) => {
    "use server";
    const data = await client.getPokemonDetails(poke);
                       ^^^^^^
    console.log(data);
  };

You can't reference to a variable in the closure that is not serializable (it's ok if from the module-level though).

One potential fix is to create the client inside that action. Or just move the entire thing into a separate "use server" file.

github-actions[bot] commented 1 year ago

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.