preface

In the case of presentation, there are usually several presentation states (take list request for example) : when the data is empty, the interface is wrong, the data is loading, the data is normal, etc., the corresponding view needs to be correctly judged and rendered during rendering, which is what we will talk about today. Unlike Vue’s V-IF, V-show and other apis, React conditional rendering is a native JS method with a bit of a hack. There are several ways to implement conditional expressions in React, and different methods are suitable for different scenarios, depending on what problem you need to deal with.

An overview of the

React conditional rendering is implemented in several ways:

  • If/Else
  • Return NULL prevents rendering
  • variable
  • Ternary operator
  • Operator (&&)
  • Self-executing functions (IIFE)
  • Child components

If/Else

Create two components, one is logged in state prompt component, one is not logged in prompt component

function UserGreeting(props) { return <h1>Welcome back! </h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; }Copy the code

Create a new Greeting component that determines which of the above components to display based on whether the user is logged in.

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}
ReactDOM.render(
  // Try changing to isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);
Copy the code

If/Else is the easiest way to implement conditional rendering. It has the advantage that it is easy to use in simple scenarios and is understood by every programmer.

Return NULL prevents rendering

If you want to hide a component, you can make the render function of the component return NULL. There is no need to use an empty div or other element as a placeholder.

Note that even if null is returned and the component is “invisible,” its life cycle will still run. For example, create a timer component

import { Component } from 'react' class Number extends Component{ constructor (props) { super(props) } componentDidUpdate() { console.log('componentDidUpdate'); } render () { if (this.props.number % 2 ! Else {return (<div className="count_wrap"> <h1> timer: {this.props.number}</h1> </div> ) } } } export default NumberCopy the code

And calls the Number component in the App component

import { Component } from 'react'
import Number from './Number.js'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
    this.onClick = this.onClick.bind(this)
  }
  onClick () {
    this.setState(prevState => ({
      count: prevState.count + 1
    }));
  }
  render() {
    return (
      <div>
        <Number number={this.state.count} />
        <button onClick={this.onClick}>Count</button>
      </div>
    )
  }
}

ReactDOM.render( <App />, document.getElementById('root') );

Copy the code

The Number component is only displayed if it is even. The render function returns null on odd numbers. However, when you look at console, the componentDidUpdate function executes every time, regardless of what the Render function returns.

Another benefit of returning null instead of an empty div is that it slightly improves the performance of the entire React application, since React does not require unmounting the empty div during updates.

variable

You can use variables to store JSX elements. It is initialized only when the condition is true, and the rest of the render does not change. For example, define a stateless component for login and logout:

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}
Copy the code

In the following example, we will create a stateful component called LoginControl.

It will determine the value of our constant button based on the current state and render
or
based on the button.

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }
    return (
      <div>
        {button}
      </div>
    );
  }
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);
Copy the code

Ternary operator

We can use ternary operators instead of if/else blocks:

condition ? expr_if_true : expr_if_false
Copy the code

For example, add a description of the user login state to the previous example

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.    </div>
  );
}
Copy the code

The entire operator can be placed inside {} of JSX, and each expression can be wrapped around JSX with () to improve readability. Using the ternary operator, you can change the isLoggedIn state within the component to display the current user’s login state.

Operator (&&)

In JavaScript, true && expression always returns expression, and false && expression always returns false.

Therefore, if the condition is true, the element to the right of && will be rendered, if it is false, React will ignore and skip it. For example, when you either render a component or do not render it, you can use the && operator. For example, our timer example above can be modified as follows:

import { Component } from 'react' class Number extends Component{ constructor (props) { super(props) } componentDidUpdate() { console.log('componentDidUpdate'); } render () {const isEven = this.props. Number % 2 === 0 return isEven && (<div className="count_wrap"> <h1> timer: {this.props.number}</h1> </div> ) } } export default NumberCopy the code

If isEven is true, the Number component is displayed; If isEven is false, the Number component is ignored. The final rendered result is consistent with the example in return NULL.

Self-executing functions (IIFE)

As the name implies, self-executing functions are executed immediately after they are defined; there is no need to call them explicitly.

This code is as follows:

(function myFunction(/* arguments */) {
  // ...
})(/* arguments */);

Copy the code

In React, you can wrap an entire self-executing function in curly braces, put all the logic inside it (if/else, switch, ternary operators, etc.), and then return whatever you need to render. Examples are as follows:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
        {
          (() => {
            let button = null;
            if (isLoggedIn) {
              button = <LogoutButton onClick={this.handleLogoutClick} />;
            } else {
              button = <LoginButton onClick={this.handleLoginClick} />;
            }
            return button
          })()
        }
    </div>
  );
}
Copy the code

Child components

This is a variant of IIFE, that is, replacing the immediate function with a normal function. We extract the BtnControl subcomponent from the IIFE example above, and use props to accept enough data for its presentation.

import { Component } from 'react'
function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}

class BtnControl extends Component {
  render() {
    const { isLoggedIn, onLogin, onLogout } = this.props;
    const subLogoutClick = () => {
      onLogout()
    }
    const subLoginClick = () => {
      onLogin()
    }

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={subLogoutClick} />;
    } else {
      button = <LoginButton onClick={subLoginClick} />;
    }
    return (
      <div>
        {button}
      </div>
    );
  }
}
export default BtnControl

Copy the code

The BtnControl component is then introduced in the Render of the LoginControl component

function render() {
  return (
    <div>
     <BtnControl isLoggedIn={isLoggedIn} onLogout={this.handleLogoutClick} onLogin={this.handleLoginClick}/>
    </div>
  );
}


Copy the code

conclusion

There are several ways to implement conditional rendering in React, and you’re free to choose any of them. You can find the best solution for the situation for these reasons:

  • It is recommended in code when the project is simple or when the logical validation of conditional rendering cannot be reused&&Or ternary operators, IIFE and other direct implementation of conditional rendering.
  • When the project is very complex, try to use sub-functions, sub-components and other ways to do a more abstract degree of conditional rendering.
  • When doing logical abstractions, consider the complexity of the project to avoid the cost of abstractions and the fragmentation of a project that can be understood as a whole.