ReactJs - 创建一个"If"组件......一个好主意?

Bra*_*rks 53 javascript reactjs

我在React文档中读到"if"类​​型语句不能在JSX代码中使用,因为JSX呈现为javascript的方式,它并没有像人们期望的那样工作.

但有没有理由为什么实现"if"组件是一个坏主意?它似乎从我最初的测试中运行良好,让我想知道为什么不经常这样做?

我的部分目的是尽可能地让反应开发,基于标记 - 尽可能少的javascript.对我而言,这种方法更像是一种"数据驱动"方法.

你可以在这里查看JS Fiddle

<script type='text/javascript' src="https://unpkg.com/react@0.11.0/dist/JSXTransformer.js"></script>
<script type='text/javascript' src="https://unpkg.com/react@0.11.0/dist/react-with-addons.js"></script>

<script type="text/jsx">
/** @jsx React.DOM */
    
var If = React.createClass({
  displayName: 'If',

  render: function()
  {
    if (this.props.condition)
      return <span>{this.props.children}</span>
    return null;
  }
});

var Main = React.createClass({
    render: function() {
        return (
           <div>
             <If condition={false}>
                <div>Never showing false item</div>
             </If>
             <If condition={true}>
                <div>Showing true item</div>
             </If>
          </div>
        );
    }
});

React.renderComponent(<Main/>, document.body);
</script>
Run Code Online (Sandbox Code Playgroud)

运行以上结果:

显示真实的项目

hug*_*omg 62

查看react文档中的JSX中If-Else部分.

在JSX中,您不能将语句放在花括号中 - 仅表达式.如果您不知道JavaScript中表达式与语句之间的区别,请阅读本文.这个限制是因为JSX去了函数调用,你不能使用if语句作为JavaScript函数的参数.但是,您可以使用布尔运算符(&&,||? :)来执行类似的工作.它们是表达式,因此它们可以适合JSX生成的构造函数调用,并且它们的短路评估与if语句中使用的相同.

<div>
    {(true
        ? <div>Showing true item</div>     
        : <div>Never showing false item</div>
    )}
</div>
<p>My name is {this.name || "default name"}</p>
Run Code Online (Sandbox Code Playgroud)

另外,React将把nullfalse作为一个"空组件"来处理,而不是在真正的DOM中呈现(目前它在幕后使用相同的noscript技巧).当您不想要"else"分支时,这很有用.有关详细信息,请参阅JSX中的False.

<div>
    {shouldIncludeChild ? <ChildComponent/> : false}
</div>
Run Code Online (Sandbox Code Playgroud)

至于你询问的If组件,它遇到的一个问题是,即使条件为假,它也会以当前形式评估其子组件.如果条件为真,那么当If的主体才有意义时,这可能会导致错误:

<If condition={person !== null}>
    //This code throws an exception if this.person is null
    <div>{person.name}</div>
</If>
Run Code Online (Sandbox Code Playgroud)

您可以通过让if组件将body作为函数接收而不是作为子组件列表来解决这个问题,但它更详细:

<If condition={person !== null} body={function(){
    return <div>{person.name}</div>
}/>
Run Code Online (Sandbox Code Playgroud)

最后,由于If组件是无状态的,因此您应该考虑使用普通函数而不是新的组件类,因为这会使"If"对React的协调算法透明.如果使用If组件,则a <div>和a <If><div>将被视为不兼容,React将执行完全重绘,而不是尝试将新组件与旧组件合并.

// This custom if function is for purely illustrative purposes
// However, this idea of using callbacks to represent block of code
// is useful for defining your own control flow operators in other circumstances.
function myCustomIf(condition, onTrue, onFalse){
    onTrue  = onTrue  || function(){ return null }        
    onFalse = onFalse || function(){ return null }
    if(condition){
        return onTrue();
    }else{
        return onFalse();
    }
}

<div>    
    {myCustomIf(person !== null, function(){
         return <div>{person.name}</div>
     })}
</div>
Run Code Online (Sandbox Code Playgroud)


Seb*_*ber 34

你不需要普通的JS.

安全可读(但冗长)

maybeRenderPerson: function() {
    var personName = ...;
    if ( personName ) {
        return <div className="person">{personName}</div>;
    }
}

render: function() {
    return (
       <div className="component">
          {this.maybeRenderPerson()}
       </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

它有点冗长,但它允许在较小的,集中的块中轻松地分割逻辑.当组件开始变得复杂时,这是最可读的.


简洁易读(但危险)

render: function() {
    var personName = ...; // present or absent name, but never ""
    return (
       <div className="component">
          {personName && (
            <div className="person">{personName}</div>
          )}
       </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

如果测试变量可能是假的值0,""或者如此,则此语法可能非常危险false.特别是对于数字,如果要确保它呈现为0,则应该稍微修改测试:

render: function() {
    var counter= ...; // number, can be 0
    return (
       <div className="component">
          {(typeof counter !== 'undefined') && (
            <div className="counter">{counter}</div>
          )}
       </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

当组件变得复杂时,拆分成多个较小的组件,并具有代码样式约定可以帮助保持其可读性:

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)

现代语法(但为时尚早)

do功能无状态组件的表示法可用于表达性而不会失去可读性.您可以轻松地将大型组件拆分为使用该do表示法的非常小且集中的组件:

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)

这有点像在JSX中使用模块模式,所以它非常灵活,但是它的样板很少.

要启用此功能,您需要ES7 stage 0编译工具,并且您最喜欢的IDE的支持可能尚不存在.

  • 到目前为止,我读过的最准确的答案是因为它超级惯用.好主意. (4认同)

Cha*_*ira 16

你可以做这样的内联条件

{true && (
<div>render item</div>
)}

{false && (
<div>don't render item</div>
)}
Run Code Online (Sandbox Code Playgroud)

或者你可以使用var

var something;

if (true) {
something = <div>render item</div>
}

{something}
Run Code Online (Sandbox Code Playgroud)


bal*_*and 5

实验性 ES7do语法非常适合这种情况。如果您使用 Babel,请启用该es7.doExpressions功能,然后:

render() {
  var condition = false;

  return (
    <div>
      {do {
        if (condition) {
          <span>Truthy!</span>;
        } else {
          <span>Not truthy.</span>;
        }
      }}
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

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


rcl*_*lai 5

您也可以在适当的上下文中执行自执行功能(尽管在Babel的帮助下)!我更喜欢这种方式,因为不需要分配变量,并且您可以根据需要进行复杂设置(尽管出于可维护性考虑,您可能不应该这样做):

render() {
  return (
    <div>
      <div>Hello!</div>
      {() => {
        if (this.props.isLoggedIn) {
          return <Dashboard />
        } else {
          return <SignIn />
        }
      }()}
      <div>Another Tag</div>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)