React Conditional Rendering (條件渲染)

在 React 有幾種條件式的寫法,讓你用來判斷在不同的資料條件下,分別該返回哪一個對應的 UI 畫面。

JavaScript if else | 三元運算子 ? :

你可以使用 JavaScript 的 if三元運算子 (Conditional (ternary) Operator)

例如顯示登入狀態的元件:

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  
  // 如果已登入,返回 <UserGreeting /> UI
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  // 如果未登入,返回 <GuestGreeting /> UI
  return <GuestGreeting />;
}

ReactDOM.render(
  // isLoggedIn (true/false) props 用來控制目前是否登入
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

上面的 Greeting 也可以寫成:

function Greeting(props) {
  return props.isLoggedIn ? <UserGreeting /> : <GuestGreeting />;
}

點我看這個例子的結果

Element Variables

如果只有畫面的一部分會變動時,你也可以將元素先放到變數裡面,當作一個動態值供後續渲染。

例子:

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;
    
    // 根據目前 isLoggedIn 狀態,將對應的按鈕 UI 元素先存在 button 變數中
    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    // 可以直接在元件的 JSX 中引用這個變數
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

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

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

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

點我看這個例子的結果

Inline && 邏輯運算子

你可以在 JSX{ } 中使用 && Logical Operator。

語法是:

{條件式 && 元素}

如果條件式是 true 則顯示元素,反之 false 則不顯示東西。

例子:

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  // 如果有未讀信件 unreadMessages.length,則顯示未讀訊息
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);

點我看這個例子的結果

Inline 三元運算子 ? :

你可以在 JSX 的 { } 中使用 三元運算子 ? :

語法是:

{條件式 ? 當條件是為真顯示的元素 : 當條件是為否顯示的元素}

例如:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

上面的括號 ( ) 是為了可讀性,你拿掉也不會有錯誤,不要忘記 JSX 只是一個 JavaScript expression。

不要顯示元素

在某些條件下,你會希望元件不要顯示任何東西,很簡單,你就直接從元件的 render() 方法 return nullfalse

// 如果是 functional component 沒有 render()
// 一樣是直接用 return null
function WarningBanner(props) {
  // 如果沒有需要顯示的警告訊息
  if (!props.warn) {
    // 畫面上就不要出現任何東西
    return null;
  }

  return (
    <div className="warning">
      Warning!
    </div>
  );
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {showWarning: true}
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  // 切換警告顯示狀態
  handleToggleClick() {
    this.setState(prevState => ({
      showWarning: !prevState.showWarning
    }));
  }
  
  render() {
    return (
      <div>
        <WarningBanner warn={this.state.showWarning} />
        <button onClick={this.handleToggleClick}>
          {this.state.showWarning ? 'Hide' : 'Show'}
        </button>
      </div>
    );
  }
}

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

點我看這個例子的結果