ReactJs - Creating an “If” component… a good idea?

后端 未结 13 2288
南旧
南旧 2020-12-12 17:11

I\'ve read in the React docs that \"if\" type statements can\'t be used in JSX code, because of the way JSX renders into javascript, it doesn\'t work out as one would expect

相关标签:
13条回答
  • 2020-12-12 17:26

    I would try to avoid conditional rendering with "templates" altogether. In React and JSX you can use the full set of JavaScript functionality to make conditional rendering happen:

    • if-else
    • ternary
    • logical &&
    • switch case
    • enums

    That's what makes the rendering with JSX so powerful. Otherwise one could invent again own templating languages that are library/framework specific like in Angular 1/2.

    0 讨论(0)
  • 2020-12-12 17:26

    render-if is a light weight function that will render an element if a condition is satisfied

    As an in-line expression

    class MyComponent extends Component {
      render() {
        return (
          {renderIf(1 + 2 === 3)(
            <span>The universe is working</span>
          )}
        );
      }
    }
    

    As a named function

    class MyComponent extends Component {
      render() {
        const ifTheUniverseIsWorking = renderIf(1 + 2 === 3);
        return (
          {ifTheUniverseIsWorking(
            <span>The universe is still wroking</span>
          )}
        )
      }
    }
    

    As a composed function

    const ifEven = number => renderIf(number % 2 === 0);
    const ifOdd = number => renderIf(number % 2 !== 0);
    
    class MyComponent extends Component {
      render() {
        return (
          {ifEven(this.props.count)(
            <span>{this.props.count} is even</span>
          )}
          {ifOdd(this.props.count)(
            <span>{this.props.count} is odd</span>
          )}
        );
      }
    }
    
    0 讨论(0)
  • 2020-12-12 17:30

    I think it depends on the case. I just had the same question that why I'm here. I just think that if the component to render is huge, it can be usefull to have an IF component instead of the standard conditional rendering method.

    ...
    <IF condition={screenIs("xs")}>
           <div> Then statement</div>
           <div>other Statement</div>
           <div>and so on</div>
    </IF>
    ...
    

    is definitively more readable than

    ...
    {
      screenIs("xs") &&  (
         <Fragment>
             <div> Then statement</div>
             <div>other Statement</div>
             <div>and so on</div>
          </Fragment>
        )
     }
     ...
    

    also for ternary statement,

    ...
    <IF.Ternary condition={screenIs("xs")}>
       <Fragment>
           <div> Then statement</div>
           <div>other then Statement</div>
           <div>and so on</div>
       </Fragment>
       <Fragment>
           <div> Else statement</div>
           <div>other Else Statement</div>
           <div>and so on</div>
       </Fragment>
     </IF.Ternary>
     ...
    

    is more readable than

    ...
    {
      screenIs("xs")
       ? (
         <Fragment>
             <div> Then statement</div>
             <div>other Then Statement</div>
             <div>and so on</div>
          </Fragment>
        )
        : (
         <Fragment>
             <div> Else statement</div>
             <div>other Else Statement</div>
             <div>and so on</div>
          </Fragment>
        )
     }
     ...
    

    anyway, to make it more readable, you can just define your conditional rendering part in some method and call it in your main render

    {
      ...
      renderParts = () => {
        return screenIs('xs') ? <div>XS</div> : <div>Not XS</div>
      }
      ...
      render() {
        return (
          ...
          {this.renderParts()}
          ...
        )
      }
     }
    
    0 讨论(0)
  • 2020-12-12 17:31

    I think your main question is not "Can I implement an If component" (because clearly you can), but "Is there any reason why implementing an If component is a bad idea?"

    The main reason it's a bad idea is because an adds component render cycles to what would otherwise be a small amount of code in an existing component. The extra component wrapper means that React needs to run an entire extra render cycle on its children. This is not a big deal if the If component is only used in one place, but if your app is littered with them, you've just made your UI that much slower.

    Similar to how: <div>Hi</div> is more efficient than <div><div>Hi</div></div>.

    0 讨论(0)
  • 2020-12-12 17:34

    You don't need anything than plain JS.

    Safe and readable (but verbose)

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

    It is a bit verbose, but it permits to easily split your logic in smaller, focused blocks. When components start to become complex, this is the most readable.


    Concise and readable (but dangerous)

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

    This syntax can be quite dangerous if the tested variable can be falsy values like 0,"" or false. Particularly with numbers you should rather modify the test slightly if you want to make sure it renders for 0:

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

    When components become complex, splitting into multiple smaller components, and having code-style conventions can help to keep it readable:

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

    Modern syntax (but too early)

    The do notation with functional stateless components can be useful for expressiveness without loosing readability. You can easily split a large component into very small and focused ones that use the do notation:

    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}/>
    }
    

    It is a bit like using the module pattern inside JSX, so it's quite flexible, but with a lot less boilerplate.

    To enable this, you need ES7 stage 0 compilation tooling, and support from your favorite IDE might not exist yet.

    0 讨论(0)
  • 2020-12-12 17:36

    For me is enough taking advantage of the lazy evaluation in a logic expression if no else statement is needed:

    render() {
        return(
            <div>
                 {
                     condition &&
                         <span>Displayed if condition is true</span>
                 }
            </div>
        );    
    }
    

    Or the ternay operator if an else is needed:

    render() {
        return(
            <div>
                 {
                     condition ?
                         <span>Displayed if condition is true</span>
                              :
                         <span>Displayed if condition is false</span>
                 }
            </div>
        );    
    }
    
    0 讨论(0)
提交回复
热议问题