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

后端 未结 13 2286
南旧
南旧 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:20

    You can do a self-executing function, with the right context too (with the help of Babel though)! Which I prefer because there's no need for assigning of variables and you can be as complex as you want (though you probably shouldn't for the sake of maintainability):

    render() {
      return (
        <div>
          <div>Hello!</div>
          {() => {
            if (this.props.isLoggedIn) {
              return <Dashboard />
            } else {
              return <SignIn />
            }
          }()}
          <div>Another Tag</div>
        </div>
      );
    }
    
    0 讨论(0)
  • 2020-12-12 17:21

    ES7 do closure is great for that:

    For example, if you're using webpack - you can add ES7 features:

    Firstly install stage-0 features with:

    npm install babel-preset-stage-0 -save-dev;
    

    Then in webpack loaders settings, add stage-0 babel preset:

        loaders : [
            //...
            {
                test : /\.js$/,
                loader : "babel-loader",
                exclude : /node_modules/,
                query : {
                    presets : ["react", "stage-0", "es2015"]
                }
            }
        ]
    

    Then your component render function can look like:

    import React , { Component } from "react";
    
    class ComponentWithIfs extends Component {
    
        render() {
            return (
                <div className="my-element">
                    {
                        do {
                            if ( this.state.something ) {
                                <div>First Case</div>
                            } else {
                                <div>2nd Case</div>
                            }
                        }
                    }
                </div>
            );
        }
    }
    
    0 讨论(0)
  • 2020-12-12 17:23

    The experimental ES7 do syntax is really nice for this situation. If you're using Babel, enable the es7.doExpressions feature then:

    render() {
      var condition = false;
    
      return (
        <div>
          {do {
            if (condition) {
              <span>Truthy!</span>;
            } else {
              <span>Not truthy.</span>;
            }
          }}
        </div>
      );
    }
    

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

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

    If anyone is interested, I just released a react module for these purposes:

    var Node = require('react-if-comp');
    ...
    React.createClass({
        render: function() {
            return (
                <div>
                    <Node if={false} else={<div>Never showing false item</div>} />
                    <Node if={true} then={<div>Showing true item</div>} />
                </div>
            );
        }
    });
    
    0 讨论(0)
  • 2020-12-12 17:24

    For maintainable code skip unnecessary abstractions like If and add some control logic with an early termination before the return statement in your render method, e.g.

    import React from 'react-native';
    
    let {
      Text
    } = React;
    
    let Main = React.createClass({
      setInitialState() {
        return { isShown: false }
      },
      render() {
        let content;
        if (this.state.isShown) {
          content = 'Showing true item'
        } else {
          return false;
        }
        return (
          <Text>{content}</Text>
        );
      }
    });
    

    Keeps you DRY. Lasting protection.

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

    Check out the If-Else in JSX section in the react Docs.

    In JSX, you can't put statements inside curly braces--only expressions. If you don't know the difference between expressions vs statements in JavaScript read this article. This limitation is because JSX desugars into function calls and you can't use if-statements as arguments to a function in JavaScript. However, you can use boolean operators (&&, || and ? :) to do a similar job. They are expressions so they can fit inside the constructor calls JSX generates and their short-circuiting evaluation is the same as the one used in if statements.

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

    Additionally, React will treat null and false as an "empty component" that does not get rendered in the real DOM (currently it uses that same noscript trick behind the scenes). This is useful when you don't want an "else" branch. See False in JSX for details.

    <div>
        {shouldIncludeChild ? <ChildComponent/> : false}
    </div>
    

    As for the If component you asked about, one problem it has is that in its current form it will evaluate its children even if the condition is false. This can lead to errors when the body of the If only makes sense if the condition is true:

    <If condition={person !== null}>
        //This code throws an exception if this.person is null
        <div>{person.name}</div>
    </If>
    

    You could workaround this by having the if component receive the body as a function instead of as a list of child components but its more verbose:

    <If condition={person !== null} body={function(){
        return <div>{person.name}</div>
    }/>
    

    Finally, since the If component is stateless, you should consider using a plain function instead of a new component class, as this would make the "If" transparent to React's reconciliation algorithm. If you use an If component, then a <div> and a <If><div> will be considered incompatible and React will do a full redraw instead of trying to merge the new component with the old one.

    // 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>
    
    0 讨论(0)
提交回复
热议问题