最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What's the right way to do `onClick` in a NextJS component? - Stack Overflow

programmeradmin7浏览0评论

Doing my project with NextJS I encounter a part where I made a ponent called app_buttonGray and it looks like this:

// /ponents/app_buttonGray.js
export default function AppButtonGray({ size, children }){
    return(
        <button className={`flex w-${size ? size : "36"} mt-2 p-1 rounded-md bg-gray-500 hover:bg-gray-800 shadow-lg justify-center`}>
            {children}
        </button>
        
    )
}

Later in my page I want to create multiple buttons but each of them have different purposes So I want to implement onClick like this:

<AppButtonGray size="48" onClick={ () => alert(1)}>New project</AppButtonGray>
<AppButtonGray size="48" onClick={ () => alert(2)}>Open project</AppButtonGray>

But that doesn't seem to work...

After multiple intents I e up with this modification that made it work:

// /ponents/app_buttonGray.js
export default function AppButtonGray({ size, onClick, children }){
    return(
        <button onClick={onClick} className={`flex w-${size ? size : "36"} mt-2 p-1 rounded-md bg-gray-500 hover:bg-gray-800 shadow-lg justify-center`}>
            {children}
        </button>
        
    )
}

So I had to pass by parameter the onClick and then call it inside the ponent...

Is that the right way to make this work? If not then what's the right way? Thanks

Doing my project with NextJS I encounter a part where I made a ponent called app_buttonGray and it looks like this:

// /ponents/app_buttonGray.js
export default function AppButtonGray({ size, children }){
    return(
        <button className={`flex w-${size ? size : "36"} mt-2 p-1 rounded-md bg-gray-500 hover:bg-gray-800 shadow-lg justify-center`}>
            {children}
        </button>
        
    )
}

Later in my page I want to create multiple buttons but each of them have different purposes So I want to implement onClick like this:

<AppButtonGray size="48" onClick={ () => alert(1)}>New project</AppButtonGray>
<AppButtonGray size="48" onClick={ () => alert(2)}>Open project</AppButtonGray>

But that doesn't seem to work...

After multiple intents I e up with this modification that made it work:

// /ponents/app_buttonGray.js
export default function AppButtonGray({ size, onClick, children }){
    return(
        <button onClick={onClick} className={`flex w-${size ? size : "36"} mt-2 p-1 rounded-md bg-gray-500 hover:bg-gray-800 shadow-lg justify-center`}>
            {children}
        </button>
        
    )
}

So I had to pass by parameter the onClick and then call it inside the ponent...

Is that the right way to make this work? If not then what's the right way? Thanks

Share Improve this question asked Jun 30, 2021 at 1:02 RicardoRicardo 1,3562 gold badges11 silver badges22 bronze badges 3
  • 1 FYI your tailwind dynamic width classname will be removed at build because you can't use string concatenation - here is a more detailed explanation and fix I posted a few days ago - stackoverflow./a/68029107/15304814 – Sean W Commented Jun 30, 2021 at 4:13
  • @SeanW thank you. I learned a lot. I think in my code this is not the case... for what I read in the links you posted I should not use string concatenation to create class names, instead I should` Do dynamically select a plete class name` which is my case – Ricardo Commented Jun 30, 2021 at 13:16
  • 1 Yes, in your case you could make the "size" the whole tailwind classname instead of just the width number - i.e. lg = "w-36" md = "w-30" etc and in your class className={${size} flex}. Lastly, since the size prop is optional you should set your default size in defaultProps to 'w-36'. AppButtonGray.defaultProps = { size: 'w-36' } reactjs/docs/… – Sean W Commented Jun 30, 2021 at 19:39
Add a ment  | 

2 Answers 2

Reset to default 3

Yes this is the right way to acplish what you're trying to do. In React you always have to pass any custom props down to the elements you are returning if you want them to be applied.

One alternative way to acplish this however is by using the rest syntax (...) to grab all of the remaining props passed to your ponent and spreading them onto the child ponent.

//                                                      Get the remaining props
export default function AppButtonGray({ size, children, ...props }) {
  return (
    <button
      className={`flex w-${
        size || "36"
      } mt-2 p-1 rounded-md bg-gray-500 hover:bg-gray-800 shadow-lg justify-center`}
      {...props}
    >
      {children}
    </button>
  );
}

This is an effective way to pass any props you'd like to your child ponent but it can be worse for readability when trying to understand the ponent. This is why some ESLint configs disallow this strategy (you can read more about that here).

Personally I think you should stick to the way you made it in most cases, you'll thank yourself in the long run when trying to understand the code you wrote.

You can simply use onClick like you used it:

type Props = {
  children: React.ReactNode;
  onClick?: (e: any) => void;
};

const Button: React.FC<Props> = ({ children, onClick }) => {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
};

export default Button;

Now in your parent, you can simply parse a function. But make sure you use "use client":

"use client"
import Button from "./Button";

<Button onClick={() => {alert("test");}}>Click</Button>
发布评论

评论列表(0)

  1. 暂无评论