如何使用条件元素并使Facebook React的JSX保持DRY?

JavaScript

Tom卡卡西

2020-03-10

如何在JSX中选择性地包含元素?这是一个使用横幅的示例,如果已传递该横幅,则该横幅应位于组件中。我要避免的是必须在if语句中复制HTML标记。

render: function () {
    var banner;
    if (this.state.banner) {
        banner = <div id="banner">{this.state.banner}</div>;
    } else {
        banner = ?????
    }
    return (
        <div id="page">
            {banner}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

第484篇《如何使用条件元素并使Facebook React的JSX保持DRY?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

22个回答
理查德Green 2020.03.10

只是为了扩展@Jack Allan对文档的引用。

null在这种情况下,React基本(快速入门)文档会提出建议但是,高级指南中也提到了布尔值,空值和未定义

Ss Yy 2020.03.10

只是添加另一个选项-如果您喜欢/容忍coffee-script,则可以使用coffee-react编写JSX,在这种情况下if / else语句是可用的,因为它们是coffee-script中的表达式,而不是语句:

render: ->
  <div className="container">
    {
      if something
        <h2>Coffeescript is magic!</h2>
      else
        <h2>Coffeescript sucks!</h2>
    }
  </div>  
Stafan路易 2020.03.10

如果仅在满足传递条件的情况下仅渲染某些内容,则可以使用以下语法:

{ condition && what_to_render }

以这种方式编写的代码如下所示:

render() {
    const { banner } = this.state;
    return (
        <div id="page">
            { banner && <div id="banner">{banner}</div> }
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

当然,还有其他有效的方法可以做到这一点,这完全取决于个人喜好和场合。如果您有兴趣,可以在本文中了解更多有关如何在React中进行条件渲染的方法

飞云泡芙 2020.03.10

还有一种使用渲染道具对组件进行条件渲染的技术。这样做的好处是,在满足条件之前,渲染器不会进行评估,因此无需担心nullundefined值。

const Conditional = ({ condition, render }) => {
  if (condition) {
    return render();
  }
  return null;
};

class App extends React.Component {
  constructor() {
    super();
    this.state = { items: null }
  }

  componentWillMount() {
    setTimeout(() => { this.setState({ items: [1,2] }) }, 2000);
  }

  render() {
    return (
      <Conditional
        condition={!!this.state.items}
        render={() => (
          <div>
            {this.state.items.map(value => <p>{value}</p>)}
          </div>
        )}
      />
    )
  }
}
小卤蛋Davaid 2020.03.10

我喜欢立即调用函数表达式(IIFE)以及if-elseover render callbacks的明确性ternary operators

render() {
  return (
    <div id="page">
      {(() => (
        const { banner } = this.state;
        if (banner) {
          return (
            <div id="banner">{banner}</div>
          );
        }
        // Default
        return (
          <div>???</div>
        );
      ))()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

您只需要了解IIFE语法,这{expression}就是常用的React语法,在其中只需考虑您正在编写一个调用自身的函数即可。

function() {

}()

需要包裹在括号内

(function() {

}())
猿樱 2020.03.10

我认为这没有被提及。这就像您自己的答案,但我认为它甚至更简单。您始终可以从表达式中返回字符串,并且可以将jsx嵌套在表达式中,因此可以轻松读取内联表达式。

render: function () {
    return (
        <div id="page">
            {this.state.banner ? <div id="banner">{this.state.banner}</div> : ''}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpf1/t39.3284-6/10574688_1565081647062540_1607884640_n.js"></script>
<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpa1/t39.3284-6/10541015_309770302547476_509859315_n.js"></script>
<script type="text/jsx;harmony=true">void function() { "use strict";

var Hello = React.createClass({
  render: function() {
    return (
      <div id="page">
        {this.props.banner ? <div id="banner">{this.props.banner}</div> : ''}
        <div id="other-content">
          blah blah blah...
        </div>
      </div>
    );   
  }
});

var element = <div><Hello /><Hello banner="banner"/></div>;
React.render(element, document.body);

}()</script>

凯斯丁 2020.03.10

也许它可以帮助遇到以下问题的人:React中的所有条件渲染这是一篇有关React中条件渲染的所有不同选项的文章。

何时使用哪种条件渲染的关键要点:

** 如果别的

  • 是最基本的条件渲染
  • 初学者友好
  • 使用if是否通过返回null提前退出渲染方法

**三元运算符

  • 在if-else语句上使用它
  • 比if-else更简洁

**逻辑&&运算符

  • 当三元运算的一侧将返回null时使用它

**开关盒

  • 冗长的
  • 只能内联自调用功能
  • 避免它,使用枚举代替

**枚举

  • 完美地映射不同的状态
  • 完美地映射多个条件

**多级/嵌套条件渲染

  • 出于可读性考虑,避免使用它们
  • 使用自己的简单条件渲染将组件拆分为更轻量的组件
  • 使用HOC

** HOC

  • 用它们来屏蔽条件渲染
  • 组件可以专注于其主要目的

**外部模板组件

  • 避免使用它们,并熟悉JSX和JavaScript
斯丁Sam 2020.03.10

您可以使用三元运算符有条件地包含元素,如下所示:

render: function(){

         return <div id="page">

                  //conditional statement
                  {this.state.banner ? <div id="banner">{this.state.banner}</div> : null}

                  <div id="other-content">
                      blah blah blah...
                  </div>

               </div>
}
樱Davaid 2020.03.10

您可以使用一个函数并返回该组件,并使呈现函数变薄

class App extends React.Component {
  constructor (props) {
    super(props);
    this._renderAppBar = this._renderAppBar.bind(this);
  }

  render () {
    return <div>
      {_renderAppBar()}

      <div>Content</div>

    </div>
  }

  _renderAppBar () {
    if (this.state.renderAppBar) {
      return <AppBar />
    }
  }
}
Vicky 2020.03.10

我制作了https://www.npmjs.com/package/jsx-control-statements使其更容易一些,基本上,它允许您将<If>条件定义为标签,然后将它们编译为三元ifs,以便<If>仅获取内部代码如果条件为真,则执行。

Tom阳光 2020.03.10

还有一个非常干净的单行版本... {this.props.product.title || “无题” }

即:

render: function() {
            return (
                <div className="title">
                    { this.props.product.title || "No Title" }
                </div>
            );
        }
蛋蛋蛋蛋 2020.03.10

最近做了https://github.com/ajwhite/render-if,仅在谓词通过时安全地呈现元素

{renderIf(1 + 1 === 2)(
  <span>Hello!</span>
)}

要么

const ifUniverseIsWorking = renderIf(1 + 1 === 2);

//...

{ifUniverseIsWorking(
  <span>Hello!</span>
)}
MandyJinJin路易 2020.03.10

我使用一个更明确的快捷方式:立即调用函数表达式(IIFE):

{(() => {
  if (isEmpty(routine.queries)) {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  } else if (this.state.configured) {
    return <DeviceList devices={devices} routine={routine} configure={() => this.setState({configured: false})}/>
  } else {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  }
})()}
猴子NearJinJin 2020.03.10

大多数示例都带有一行有条件呈现的“ html”。当我有多行需要有条件地呈现时,这对我来说似乎是可读的。

render: function() {
  // This will be renered only if showContent prop is true
  var content = 
    <div>
      <p>something here</p>
      <p>more here</p>
      <p>and more here</p>
    </div>;

  return (
    <div>
      <h1>Some title</h1>

      {this.props.showContent ? content : null}
    </div>
  );
}

第一个例子很好,因为代替null我们可以有条件地渲染其他一些内容,例如{this.props.showContent ? content : otherContent}

但是,如果您只需要显示/隐藏内容,这将更好,因为忽略了布尔值,空值和未定义

render: function() {
  return (
    <div>
      <h1>Some title</h1>

      // This will be renered only if showContent prop is true
      {this.props.showContent &&
        <div>
          <p>something here</p>
          <p>more here</p>
          <p>and more here</p>
        </div>
      }
    </div>
  );
}
米亚小小神乐 2020.03.10

当“ if”分支中有多个元素时,此组件有效:

    var Display = React.createClass({
        render: function() {
            if (!this.props.when) {
                return false;
            }
            return React.DOM.div(null, this.props.children);
        }
    });

用法:

      render: function() {
            return (
                <div>
                    <Display when={this.state.loading}>
                        Loading something...
                        <div>Elem1</div>
                        <div>Elem2</div>
                    </Display>
                    <Display when={!this.state.loading}>
                        Loaded
                        <div>Elem3</div>
                        <div>Elem4</div>
                    </Display>
                </div>
            );
        },

ps有人认为此组件不利于代码读取。但是在我看来,带有javascript的html更糟

斯丁Tony泡芙 2020.03.10

简单,创建一个函数。

renderBanner: function() {
  if (!this.state.banner) return;
  return (
    <div id="banner">{this.state.banner}</div>
  );
},

render: function () {
  return (
    <div id="page">
      {this.renderBanner()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

我一直都遵循这种模式。使代码真正干净且易于理解。此外,Banner如果它变得太大(或在其他地方重复使用),它还允许您将重构为自己的组件。

JinJin卡卡西小胖 2020.03.10

正如答案中已经提到的,JSX为您提供了两种选择

  • 三元运算符

    { this.state.price ? <div>{this.state.price}</div> : null }

  • 逻辑合取

    { this.state.price && <div>{this.state.price}</div> }


但是,这些不适用于 price == 0

在第一种情况下,JSX将呈现false分支,并且在逻辑合取的情况下,将不呈现任何内容。如果该属性可能为0,则只需在JSX之外使用if语句即可。

卡卡西Mandy 2020.03.10

实验性的ES7 do语法使此操作变得容易。如果您使用的是Babel,请启用该es7.doExpressions功能,然后:

render() {
  return (
    <div id="banner">
      {do {
        if (this.state.banner) {
          this.state.banner;
        } else {
          "Something else";
        }
      }}
    </div>
  );
}

参见http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions

老丝乐 2020.03.10

就我个人而言,我真的认为(JSX In Depth)中显示的三元表达式是符合ReactJs标准的最自然的方式。

请参见以下示例。乍一看有点混乱,但效果很好。

<div id="page">
  {this.state.banner ? (
    <div id="banner">
     <div class="another-div">
       {this.state.banner}
     </div>
    </div>
  ) : 
  null} 
  <div id="other-content">
    blah blah blah...
  </div>
</div>
小胖凯樱 2020.03.10

只需将横幅标为未定义即可,它就不会包含在内。

LEY逆天 2020.03.10

您也可以这样写

{ this.state.banner && <div>{...}</div> }

如果您state.bannernullundefined,则跳过条件的右侧。

GreenGil 2020.03.10

If样式组件是危险的,因为该代码块总是执行不管条件的。例如,如果banneris ,则将导致null异常null

//dangerous
render: function () {
  return (
    <div id="page">
      <If test={this.state.banner}>
        <img src={this.state.banner.src} />
      </If>
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

另一种选择是使用内联函数(对else语句特别有用):

render: function () {
  return (
    <div id="page">
      {function(){
        if (this.state.banner) {
          return <div id="banner">{this.state.banner}</div>
        }
      }.call(this)}
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

解决问题的另一种选择

render: function () {
  return (
    <div id="page">
      { this.state.banner &&
        <div id="banner">{this.state.banner}</div>
      }
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android