【问题标题】:Custom HTML Button wrapped in Link not working包含在链接中的自定义 HTML 按钮不起作用
【发布时间】:2020-03-08 23:33:28
【问题描述】:

我制作了一个自定义的Button 组件,它返回 HTML button。现在我在Link 中使用这个Button 来自next-routes。问题是它不能以这种方式工作。奇怪的是,如果我在Link 中使用 HTML button,则该按钮可以正常工作。但是,两个按钮都以完全相同的方式在 DOM 中呈现。以下是代码:

// Button.js

import React from "react";
import classNames from "classnames";

const Button = ({
    children,
    newClass = "",
    onClickHandler = () => { },
    isSubmitting = false,
    inlineBtn = true,
    disabled,
    primary,
    secondary,
    basic,
    notCentered = true,
    shaded,
    miniLoader,
    type = "button",
    isTransparent,
    fontClass = "",
    small
}) => {
    return (
        <React.Fragment>
            <button
                className={classNames(
                    `${isTransparent ? 'btn-transparent' : 'btn'} ${fontClass} ${newClass}`,
                    {
                        "btn-block": !inlineBtn,
                        "col-mx-auto": !notCentered,
                        "btn-primary": primary,
                        "btn-secondary": secondary,
                        "btn-basic": basic,
                        shaded: shaded,
                        loading: isSubmitting,
                        "loading-sm": miniLoader,
                        "btn-sm": small
                    }
                )}
                disabled={disabled}
                type={type}
                onClick={onClickHandler}
            >
                <span>{children}</span>
            </button>
        </React.Fragment>
    );
};

export { Button };

以下不起作用:

<Link route="/register/location">
  <Button basic small>
    Sign Up
  </Button>
</Link>

以下工作正常:

<Link route="/register/location">
  <button className="btn btn-basic btn-sm" type="button" onClick={() => { }}>
    <span>Sign Up</span>
  </button>
</Link>

【问题讨论】:

    标签: reactjs button react-router next.js


    【解决方案1】:

    您可以按如下方式更新您的Button 组件。

    const Button = ({
      as = "button",
      children,
      newClass = "",
      onClickHandler = () => {},
      isSubmitting = false,
      inlineBtn = true,
      disabled,
      primary,
      secondary,
      basic,
      notCentered = true,
      shaded,
      miniLoader,
      type = "button",
      isTransparent,
      fontClass = "",
      small,
      ...rest
    }) => {
      const Wrapper = as;
      return (
        <Wrapper
          className={classNames(
            `${isTransparent ? "btn-transparent" : "btn"} ${fontClass} ${newClass}`,
            {
              "btn-block": !inlineBtn,
              "col-mx-auto": !notCentered,
              "btn-primary": primary,
              "btn-secondary": secondary,
              "btn-basic": basic,
              shaded: shaded,
              loading: isSubmitting,
              "loading-sm": miniLoader,
              "btn-sm": small
            }
          )}
          disabled={disabled}
          type={type}
          onClick={onClickHandler}
          {...rest}
        >
          <span>{children}</span>
        </Wrapper>
      );
    };
    

    这将允许自定义Wrapper 用于您的Button 组件。我们将每个继承的道具传递给您的Wrapper,以便您的route 道具将在您的Link 组件中接收。

    你可以这样使用它

    <Button basic small as={Link} route="/register/location">
      Sign Up
    </Button>
    

    这使用 ES6 扩展运算符语法。基本上,您将Button 组件as 渲染为Link 组件,并且任何继承的道具都将传递给Link 组件,因此route 道具将传递给Link 组件。

    这遵循类似于 Material-ui 的 spead 方法的 API 设计方法。这也将使您的组件更加灵活。

    【讨论】:

    • 我在其他不充当链接并执行onClick() 的地方使用此按钮。在这些情况下,不需要包装器,也不应该传递。这意味着我必须为需要按钮充当链接的情况制作一个特殊的按钮。有没有更好的解决方案?
    • 是的,您可以按原样使用您的组件,因为as props 的默认值为button。这只是一个增强功能,可以让您的Button 组件更加灵活
    • 哦,好吧。但是使用这个组件需要给a标签来传递一个孩子并将类给锚。我建议,这将很难维护。但是,我接受您的解决方案,因为它正确地服务于特定目的,但它对我不起作用。非常感谢兄弟。
    • 很高兴有帮助!这种模式在很多流行的 UI 框架中都有使用。使用这种模式可以为您的组件提供更大的灵活性。 as 属性基于Semantic UI,至于Material UI,他们使用component 属性代替。他们做同样的事情,只是道具名称不同。我为您编写的示例是一个简单的示例,您可以使您的 Button 组件更加灵活。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    相关资源
    最近更新 更多