【问题标题】:What's the right way to do `onClick` in a NextJS component?在 NextJS 组件中执行“onClick”的正确方法是什么?
【发布时间】:2021-09-12 04:07:33
【问题描述】:

在使用 NextJS 进行项目时,我遇到了一个部分,其中我制作了一个名为 app_buttonGray 看起来像这样:

// /components/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>
        
    )
}

稍后在我的页面中,我想创建多个按钮,但每个按钮都有不同的用途 所以我想像这样实现onClick

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

但这似乎不起作用......

经过多次尝试后,我想出了使它起作用的修改:

// /components/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>
        
    )
}

所以我必须通过参数传递onClick,然后在组件内部调用它...

这是实现这项工作的正确方法吗?如果没有,那么正确的方法是什么?谢谢

【问题讨论】:

  • 仅供参考,您的顺风动态宽度类名将在构建时被删除,因为您不能使用字符串连接 - 这是我几天前发布的更详细的解释和修复 - stackoverflow.com/a/68029107/15304814
  • @SeanW 谢谢。我学到了很多。我认为在我的代码中情况并非如此......对于我在您发布的链接中阅读的内容,我应该not use string concatenation to create class names,而不是我应该`动态选择一个完整的类名`这是我的情况
  • 是的,在您的情况下,您可以将“大小”设为整个顺风类名,而不仅仅是宽度数字 - 即 lg = "w-36" md = "w-30" 等,并在您的类类名={${size} flex}。最后,由于 size 属性是可选的,因此您应该将 defaultProps 中的默认尺寸设置为“w-36”。 AppButtonGray.defaultProps = { size: 'w-36' } reactjs.org/docs/…

标签: javascript reactjs react-hooks onclick next.js


【解决方案1】:

是的,这是完成您想做的事情的正确方法。在 React 中,如果你想应用它们,你总是必须将任何自定义 props 传递给要返回的元素。

不过,实现此目的的另一种方法是使用rest syntax (...) 获取传递给您的组件的所有剩余道具,并将spreading 传递给子组件。

//                                                      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>
  );
}

这是将您想要的任何道具传递给子组件的有效方法,但在尝试理解组件时它可能会降低可读性。这就是为什么一些 ESLint 配置不允许这种策略 (you can read more about that here)

我个人认为在大多数情况下你应该坚持你的方式,从长远来看,当你试图理解你编写的代码时,你会感谢自己。

【讨论】:

  • 太棒了!你知道为什么第一次尝试没有成功吗?我想一旦组件已经制作完成,我就可以使用onClick
  • 它不起作用,因为您没有将 onClick 属性转发给需要它的实际 &lt;button&gt; 组件。您只是将它传递给忽略它的自定义组件。
  • 不,其余语法可用于对象和数组解构或函数参数。在这种情况下,此示例的“rest 语法”部分使用了 rest 参数的解构类型,其中 as spread 用于将 props 转发到子组件。如果您不相信我,请查看提案:github.com/tc39/proposal-object-rest-spread/blob/master/… 或查看 MDN 文档关于解构分配 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 这是一个奇怪的场景,因为它是一个函数参数,但实际上,我们正在将一个组件参数props(它是一个对象)解构为传递的各种道具名称。当您将值传递给对象、数组或函数时,总是使用术语“spread”,而每当您从对象、数组或对象中获取值时,都会使用术语“rest”。或函数参数列表。
  • 今天学到了一些东西 - 谢谢。我删除了评论以防止混淆。我一直使用将剩余变量定义为 '...rest' 来进行破坏,但总是假设它是传播标准的一部分。
猜你喜欢
  • 2021-03-21
  • 2014-07-04
  • 2019-03-12
  • 2020-06-28
  • 2012-02-25
  • 2021-08-23
  • 2012-10-15
  • 1970-01-01
  • 2015-08-08
相关资源
最近更新 更多