有条件地与react路由器链接

Conditionally linking with react-router Link

本文关键字:路由器 链接 react 有条件      更新时间:2023-09-26

我的React组件中有一种情况,即:如果this.props.isComingFromModal为false,我希望一些元素封装在Link组件中。

我做了什么(JSX):

<If condition={!this.props.isComingFromModal}>
  <Link
    to={{ pathname: `vendors/${benefit.vendor.id}`, state: { modal: false } }}
  >
    <img
      className="Benefit__vendor__thumb"
      src={benefit.vendor.tinyLogoUrl}
      alt="Ponto Frio"
    />

    <div className="Benefit__vendor__info">
      <h2 className="Benefit__vendor__title">{benefit.vendor.tradingName}</h2>
      <div className="rating">
        <Rating
          readonly
          initialRate={benefit.vendor.rating}
          className="rating"
          fractions={2}
          empty="icon-rating icon-rating--empty fa fa-star fa-2x"
          full="icon-rating fa fa-star fa-2x"
        />
      </div>
    </div>
  </Link>
  <Else />
    <img
      className="Benefit__vendor__thumb"
      src={benefit.vendor.tinyLogoUrl}
      alt="Ponto Frio"
    />

    <div className="Benefit__vendor__info">
      <h2 className="Benefit__vendor__title">{benefit.vendor.tradingName}</h2>
      <div className="rating">
        <Rating
          readonly
          initialRate={benefit.vendor.rating}
          className="rating"
          fractions={2}
          empty="icon-rating icon-rating--empty fa fa-star fa-2x"
          full="icon-rating fa fa-star fa-2x"
        />
      </div>
    </div>
</If>

但我认为这是一种重复。我不能做一些类似(JSX)的事情吗

<Link
  to={{ pathname: `vendors/${benefit.vendor.id}`, state: { modal: false } }}
  condition={!this.props.isComingFromModal}
>
  <img
    className="Benefit__vendor__thumb"
    src={benefit.vendor.tinyLogoUrl}
    alt="Ponto Frio"
  />

  <div className="Benefit__vendor__info">
    <h2 className="Benefit__vendor__title">{benefit.vendor.tradingName}</h2>
    <div className="rating">
      <Rating
        readonly
        initialRate={benefit.vendor.rating}
        className="rating"
        fractions={2}
        empty="icon-rating icon-rating--empty fa fa-star fa-2x"
        full="icon-rating fa fa-star fa-2x"
      />
    </div>
  </div>
</Link>

在这个假设场景中,我将展示Link组件,就像this.props.isComingFromModal。有办法做到这一点吗?

我的简单功能解决方案:

import React from 'react'
import { Link } from 'react-router-dom'
export default function ConditionalLink({ children, condition, ...props }) {
  return !!condition && props.to ? <Link {...props}>{children}</Link> : <>{children}</>
}

然后你可以这样使用它:

<ConditionalLink to="/path" condition={!isComingFromModal}>
  conditional link
</ConditionalLink>

您希望尽量避免JSX中的重复是正确的。对于这种情况,我有几种策略。

一个选项使用了Link只是一个ReactComponent对象的事实,并且可以分配给任何变量。你可以在render方法的开头放一条这样的线:

var ConditionalLink = !this.props.isComingFromModal ? Link : React.DOM.div;

然后只需将您的内容封装在ConditionalLink组件中即可:

return (
    <ConditionalLink>
        <img />
        <div>...</div>
    </ConditionalLink>
);

当您的条件为true时,ConditionalLink将是对Link的引用;当条件为假时,它将是一个简单的CCD_ 9。

你可能想尝试的另一个选项是在其他地方创建你想在链接内部(或不在链接内部)呈现的内容,然后基本上做你上面正在做的事情:

var content = (
    <div>
        <img />
        <div>All your content</div>
    </div>
);
return (<If condition={!this.props.isComingFromModal}>
    <Link>
        {content}
    </Link>
    <Else />
    {content}
</If>);

您还可以创建一个函数或方法来返回content,或者将其完全放在一个新组件中。

最后,为了真正回答你的问题——是的,你可以制作一个按照你想要的方式工作的链接组件!React的一大优点是可以很容易地重新混合现有组件。如果您想要一个条件链接,只需创建一个基于道具值返回{this.props.children}<Link {...this.props}>{this.props.children}</Link>的组件。

也许这已经晚了,但尽管evan的答案是正确的,但这两种情况都不适用于我。也许是因为我做了一些额外的不正确的进口,或者什么。。。但它激励我找到了另一个类似的解决方案,对我来说效果很好,所以我想在这里分享给像我这样处境相似的人

该解决方案将不将内容放入变量中,而是创建一个简单的ConditionalLink组件,该组件将接受任何内容作为具有其他必需道具(但至少是condition和路径to)的children

render() {
    const {children, to, condition} = this.props;
    let toRender;
    if (condition) {
        toRender = <Link to={to}>{children}</Link>;
    } else {
        toRender = children;
    }
    return toRender;
}

它的好处是,以后您可以将它与任何其他内容一起再次使用。例如:

<ConditionalLink condition={enabled && linkPath} to={linkPath}>
    ...content...
</ConditionalLink>