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

Jac*_*lan 226 javascript reactjs react-jsx

我如何选择在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>
    );
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*lan 150

只是将横幅保留为未定义且不包括在内.


tob*_*bik 131

那这个呢.让我们定义一个简单的帮助If组件.

var If = React.createClass({
    render: function() {
        if (this.props.test) {
            return this.props.children;
        }
        else {
            return false;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

并以这种方式使用它:

render: function () {
    return (
        <div id="page">
            <If test={this.state.banner}>
                <div id="banner">{this.state.banner}</div>
            </If>
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

更新:随着我的回答变得越来越流行,我觉得有义务警告你这个解决方案最大的危险.正如另一个答案所指出的<If />,无论条件是真还是假,组件内的代码都会被执行.因此,以下示例将失败,如果bannernull(请注意第二行的属性访问):

<If test={this.state.banner}>
    <div id="banner">{this.state.banner.url}</div>
</If>
Run Code Online (Sandbox Code Playgroud)

使用它时必须小心.我建议阅读替代(更安全)方法的其他答案.

更新2:回顾过去,这种做法不仅危险,而且非常繁琐.这是一个典型的例子,当一个开发人员(我)试图将他知道的模式和方法从一个区域转移到另一个区域但是它确实不起作用(在这种情况下是其他模板语言).

如果您需要条件元素,请执行以下操作:

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>
    );
}
Run Code Online (Sandbox Code Playgroud)

如果您还需要else分支,只需使用三元运算符:

{this.state.banner ?
   <div id="banner">{this.state.banner}</div> :
   <div>There is no banner!</div>
}
Run Code Online (Sandbox Code Playgroud)

它更短,更优雅,更安全.我用它所有的时间.唯一的缺点是你不能else if轻易地进行分支,但这通常不常见.

无论如何,这要归功于JavaScript中的逻辑运算符.逻辑运算符甚至允许这样的小技巧:

<h3>{this.state.banner.title || 'Default banner title'}</h3>
Run Code Online (Sandbox Code Playgroud)

  • 如果你在"if"标签内有多个元素,那就没有用了 (2认同)

Chi*_*edo 82

就个人而言,我真的认为http://facebook.github.io/react/tips/if-else-in-JSX.html中显示的三元表达式是符合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>
Run Code Online (Sandbox Code Playgroud)

  • @moby我认为流行的答案更具动态性,可以实现更清晰的渲染功能.使用这种方法,如果您有多个条件,会发生什么?你现在有一种疯狂的嵌套这种奇怪的格式,如果两个独立的区域需要基于条件的相同更改,你现在必须再次重写条件.只是我的意见!:) (2认同)

小智 45

你也可以这样写

{ this.state.banner && <div>{...}</div> }
Run Code Online (Sandbox Code Playgroud)

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


ben*_*ree 41

If样式组件是危险的,因为该代码块总是执行不管条件的.例如,如果banner是,则会导致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>
  );
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用内联函数(对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>
  );
}
Run Code Online (Sandbox Code Playgroud)

反应问题的另一个选择:

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,在所有解决方案中,内联功能似乎是最优雅和直接的.一个人应该注意什么? (2认同)

Seb*_*ber 22

&& +代码风格+小组件

这个简单的测试语法+代码风格约定+小型聚焦组件对我来说是最具可读性的选择.你只需要采取像falsy值的特殊照顾false,0"".

render: function() {
    var person= ...; 
    var counter= ...; 
    return (
       <div className="component">
          {person && (
            <Person person={person}/>
          )}
          {(typeof counter !== 'undefined') && (
            <Counter value={counter}/>
          )}
       </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

记谱法

ES7 stage-0表示法语法也非常好,当我的IDE正确支持时,我肯定会使用它:

const Users = ({users}) => (
  <div>
    {users.map(user =>
      <User key={user.id} user={user}/>
    )}
  </div>
)  

const UserList = ({users}) => do {
  if (!users) <div>Loading</div>
  else if (!users.length) <div>Empty</div>
  else <Users users={users}/>
}
Run Code Online (Sandbox Code Playgroud)

更多细节:ReactJs - 创建一个"If"组件......一个好主意?


Mic*_*aev 22

简单,创建一个功能.

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是我个人一直关注的模式.使代码真正干净,易于理解.更重要的是,Banner如果它太大(或在其他地方重复使用),它允许您重构为自己的组件.


bal*_*and 13

实验性的ES7 do语法使这很容易.如果您使用的是Babel,请启用该es7.doExpressions功能:

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

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


Lyu*_*mir 11

正如答案中已经提到的,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语句.


k.m*_*rov 8

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

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

用法:

      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>
            );
        },
Run Code Online (Sandbox Code Playgroud)

有人认为这些组件不适合代码阅读.但在我看来,使用javascript的html更糟糕