将回调从服务器组件传递到Next.js中的客户端组件。

huangapple go评论178阅读模式
英文:

Passing callback from server component to client component in Next.js

问题

我卡在了一个地方,我正在创建一个自定义按钮组件,将其标记为客户端组件,然后我从服务器端组件传递它的 onClick 回调,但它给我报错:

错误 Error: 无法将事件处理程序传递给客户端组件的 props
  <button onClick={function} className=... children=...>
                  ^^^^^^^^^^
如果需要交互性请考虑将部分内容转换为客户端组件
    at stringify (<anonymous>)
digest: "280571554"

这是我的 WelcomeComponent.tsx 文件:

import { faPizzaSlice } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Brand, Button } from "@/components/Common";
import Image from "next/image";

const WelcomeComponent = () => {
  return (
    <div className="border flex items-center justify-center flex-wrap space-x-10 py-10">
      <div className="font-semibold flex flex-col">
        <div className="mr-3 flex items-center text-3xl">
          <span className="mr-2">Welcome to</span>
          <Brand size="large" />
        </div>
        <h2 className="text-2xl">We Serve you with happiness.</h2>
        <Button
          text="Order Now"
          icon={<FontAwesomeIcon className="w-6" icon={faPizzaSlice} />}
          onClick={() => {
            console.log("c");
          }}
        />
      </div>
      <Image
        className="w-auto h-auto"
        height={0}
        width={300}
        src="/man.jpg"
        priority
        alt=""
      />
    </div>
  );
};

export default WelcomeComponent;

这是我的 Button.tsx 文件:

interface Props {
  text: string;
  icon: React.JSX.Element;
  onClick: () => void;
}

const Button = ({ text, icon, onClick }: Props) => {

  return (
    <button
      onClick={onClick}
      className="shadow-lg my-5 flex items-center justify-center text-white bg-orange-400 hover:bg-orange-500 rounded-md p-3 w-40 space-x-2"
    >
      <span className="text-md">{text}</span>
      {icon}
    </button>
  );
};

export default Button;

正如你所看到的,我想将 onClick 回调传递给 Button 组件,我在 WelcomeComponent.tsx 中调用它。

我正在使用 Next.js 的版本 v13.4

英文:

I am stuck at a point where I am creating a custom button component, marking it as a client component, and then I am passing its onClick callback from a server-side component, and it's giving me this error:

 error Error: Event handlers cannot be passed to Client Component props.
  &lt;button onClick={function} className=... children=...&gt;
                  ^^^^^^^^^^
If you need interactivity, consider converting part of this to a Client Component.
    at stringify (&lt;anonymous&gt;)
digest: &quot;280571554&quot;

This is my WelcomeComponent.tsx file:

import { faPizzaSlice } from &quot;@fortawesome/free-solid-svg-icons&quot;;
import { FontAwesomeIcon } from &quot;@fortawesome/react-fontawesome&quot;;
import { Brand, Button } from &quot;@/components/Common&quot;;
import Image from &quot;next/image&quot;;

const WelcomeComponent = () =&gt; {
  return (
    &lt;div className=&quot;border flex items-center justify-center flex-wrap space-x-10 py-10&quot;&gt;
      &lt;div className=&quot;font-semibold flex flex-col&quot;&gt;
        &lt;div className=&quot;mr-3 flex items-center text-3xl&quot;&gt;
          &lt;span className=&quot;mr-2&quot;&gt;Welcome to&lt;/span&gt;
          &lt;Brand size=&quot;large&quot; /&gt;
        &lt;/div&gt;
        &lt;h2 className=&quot;text-2xl&quot;&gt;We Serve you with happiness.&lt;/h2&gt;
        &lt;Button
          text=&quot;Order Now&quot;
          icon={&lt;FontAwesomeIcon className=&quot;w-6&quot; icon={faPizzaSlice} /&gt;}
          onClick={() =&gt; {
            console.log(&quot;c&quot;);
          }}
        /&gt;
      &lt;/div&gt;
      &lt;Image
        className=&quot;w-auto h-auto&quot;
        height={0}
        width={300}
        src=&quot;/man.jpg&quot;
        priority
        alt=&quot;&quot;
      /&gt;
    &lt;/div&gt;
  );
};

export default WelcomeComponent;

And this is my Button.tsx file:

interface Props {
  text: string;
  icon: React.JSX.Element;
  onClick: () =&gt; void;
}

const Button = ({ text, icon, onClick }: Props) =&gt; {

  return (
    &lt;button
      onClick={onClick}
      className=&quot;shadow-lg my-5 flex items-center justify-center text-white bg-orange-400 hover:bg-orange-500 rounded-md p-3 w-40 space-x-2&quot;
    &gt;
      &lt;span className=&quot;text-md&quot;&gt;{text}&lt;/span&gt;
      {icon}
    &lt;/button&gt;
  );
};

export default Button;

As you can see I want to pass the onClick callback to the Button component which I am calling in the WelcomeComponent.tsx.

I'm using Next.js v13.4.

答案1

得分: 1

以下是您要翻译的内容:

"That's because Server Components gets compiled to HTML and sent to the browser with no additional JavaScript, that click handler in your case. And this makes it so you can only pass non-function values from a server component to a client one.

The component that calls Button should be a client one, with &quot;use client&quot; at the top, as you need to pass a function from there, and it's okay, as Lee Robinson from Vercel says:

>Client Components aren't a de-opt, nor a cop-out. You can think of Server Components as an additive to the existing model. I understand the sentiment of wanting to use Server Components for lots of things (not bad!) but it's also totally okay to use Client Components for certain things.

&quot;use client&quot;; // Need to send a JavaScript function to the browser&#128072;&#127997;
import { faPizzaSlice } from &quot;@fortawesome/free-solid-svg-icons&quot;;
import { FontAwesomeIcon } from &quot;@fortawesome/react-fontawesome&quot;;
import { Brand, Button } from &quot;@/components/Common&quot;;
import Image from &quot;next/image&quot;;
const WelcomeComponent = () =&gt; {
return (
&lt;div className=&quot;border flex items-center justify-center flex-wrap space-x-10 py-10&quot;&gt;
&lt;div className=&quot;font-semibold flex flex-col&quot;&gt;
&lt;div className=&quot;mr-3 flex items-center text-3xl&quot;&gt;
&lt;span className=&quot;mr-2&quot;&gt;Welcome to&lt;/span&gt;
&lt;Brand size=&quot;large&quot; /&gt;
&lt;/div&gt;
&lt;h2 className=&quot;text-2xl&quot;&gt;We Serve you with happiness.&lt;/h2&gt;
&lt;Button
text=&quot;Order Now&quot;
icon={&lt;FontAwesomeIcon className=&quot;w-6&quot; icon={faPizzaSlice} /&gt;}
onClick={() =&gt; {
console.log(&quot;c&quot;);
}}
/&gt;
&lt;/div&gt;
&lt;Image
className=&quot;w-auto h-auto&quot;
height={0}
width={300}
src=&quot;/man.jpg&quot;
priority
alt=&quot;&quot;
/&gt;
&lt;/div&gt;
);
};

And even a client component first renders on the server with Next.js, so if it's for SEO, there is no worry.

英文:

That's because Server Components gets compiled to HTML and sent to the browser with no additional JavaScript, that click handler in your case. And this makes it so you can only pass non-function values from a server component to a client one.

The component that calls Button should be a client one, with &quot;use client&quot; at the top, as you need to pass a function from there, and it's okay, as Lee Robinson from Vercel says:

>Client Components aren't a de-opt, nor a cop-out. You can think of Server Components as an additive to the existing model. I understand the sentiment of wanting to use Server Components for lots of things (not bad!) but it's also totally okay to use Client Components for certain things.

&quot;use client&quot;; // Need to send a JavaScript function to the browser&#128072;&#127997;
import { faPizzaSlice } from &quot;@fortawesome/free-solid-svg-icons&quot;;
import { FontAwesomeIcon } from &quot;@fortawesome/react-fontawesome&quot;;
import { Brand, Button } from &quot;@/components/Common&quot;;
import Image from &quot;next/image&quot;;
const WelcomeComponent = () =&gt; {
return (
&lt;div className=&quot;border flex items-center justify-center flex-wrap space-x-10 py-10&quot;&gt;
&lt;div className=&quot;font-semibold flex flex-col&quot;&gt;
&lt;div className=&quot;mr-3 flex items-center text-3xl&quot;&gt;
&lt;span className=&quot;mr-2&quot;&gt;Welcome to&lt;/span&gt;
&lt;Brand size=&quot;large&quot; /&gt;
&lt;/div&gt;
&lt;h2 className=&quot;text-2xl&quot;&gt;We Serve you with happiness.&lt;/h2&gt;
&lt;Button
text=&quot;Order Now&quot;
icon={&lt;FontAwesomeIcon className=&quot;w-6&quot; icon={faPizzaSlice} /&gt;}
onClick={() =&gt; {
console.log(&quot;c&quot;);
}}
/&gt;
&lt;/div&gt;
&lt;Image
className=&quot;w-auto h-auto&quot;
height={0}
width={300}
src=&quot;/man.jpg&quot;
priority
alt=&quot;&quot;
/&gt;
&lt;/div&gt;
);
};

And even a client component first renders on the server with Next.js, so if it's for SEO, there is no worry.

huangapple
  • 本文由 发表于 2023年8月11日 01:43:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878150.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定