8

According to the Next.js docs for the app directory:

"Whenever possible, we recommend fetching data inside Server Components. Server Components always fetch data on the server."

This is great because I am hitting an external API (where I cannot change the CORS policy - Allow-Origins...).

I have a page (server component) with a form (client component), and I am trying to hit the API using the server component.

Home page

import Form from './Form';

export default function Home() {
   handleSubmit = () => {...submit logic}
   return <Form onSubmit={handleSubmit} />
}

Form Component

'use client'

export default function Form({ onSubmit }) {
 return <form onSubmit={handleSubmit}>...</form>
}

When I try to pass the handleSubmit function to the client component, I get this error:

Functions cannot be passed directly to Client Components because they're not serializable.

  1. I'm not sure what that means.
  2. Is there a way to pass functions to client components?
  3. I need to fetch from a server component because the API has CORS policy. Is it possible to do what I am trying to accomplish?

4 Answers4

2

Do you have any error.js in your directory? Add use client at the top of the file.

See reference here: https://github.com/vercel/next.js/issues/42408 https://beta.nextjs.org/docs/rendering/server-and-client-components

Hope this helps.

0
  1. I need to fetch from a server component because the API has a CORS policy. Is it possible to do what I'm trying to accomplish?

The CORS policy applies to any incoming request (whether the request comes from a front or server component doesn't matter).

What is the HTTP method you are going to use in your function? If it's POST, PUT or DELETE, you don't absolutely need to do it in a server component (the purpose of a server component is to optimize SEO by sending the data already loaded - it is called server-side rendering).

If this is a GET, what are you trying to accomplish? Dynamically load data based on what the user has chosen to fill in?

If so, I think it's easier to do this on the client side. Otherwise you don't need a form.

paulin-crtn
  • 325
  • 2
  • 9
0

do it in your home:

import Form from './Form';

handleSubmit = () => {
   'use server';

   ...submit logic
}

export default function Home() {
   return <Form onSubmit={handleSubmit} />
}
Thulio
  • 1
  • 1
0

You cannot pass a function from a server component to a client component.

Props passed from the Server to Client Components need to be serializable. This means that values such as functions, Dates, etc, cannot be passed directly to Client Components.

https://nextjs.org/docs/getting-started/react-essentials

Though it is true that data fetching is recommended to be done on the server side, passing a function that is written in a server side file to a client component does not help. It is still to be run in the client component.

To fetch data on the server side, do it in a server component, instead of just a server function. Then pass any data necessary, not functions to a client component. This design is why the data passed from server component to client component must be serializable (like the returning data from an API end point). Do not pass a function from server component to client component.

In your case, however, there is no need to fetch on the server side, because data flow with authentication is two-direction—you need to pass username and password to the server and also update the client-side status (e.g. login context) when successfully authenticated. Doing the data fetching on the server side in-between the two directions could be really hard, because the two data flows are both crossing the border. I suggest you just do it in the client component.