Умоўны рэндэрынг (Conditional Rendering)

У React’е вы можаце ствараць пэўныя кампанэнты, якія інкапсулююць патрэбныя вам паводзіны. Затым вы можаце рэндэрыць некаторыя зь іх, у залежнасьці ад стану (state) вашай прыкладной праграмы.

Умоўны рэндэрынг у React працуе такім жа чынам, як працуюць умовы (conditions) у JavaScript. Выкарыстоўвайце апэратары JavaScript, такія як if або умоўны апэратар (conditional operator), каб ствараць элемэнты, якія прадстаўляюць бягучы стан (state), і няхай React абнаўляе UI, каб прывесьці яго ў адпаведнасьць да іх.

Разгледзім гэтыя два кампанэнты:

function UserGreeting(props) {
  return <h1>Welcome back! Зь вяртаньнем!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up. Калі ласка, зарэгіструйцеся.</h1>;
}

Мы створым кампанэнт Greeting, які адлюстроўвае адзін з гэтых кампанэнтаў, у залежнасьці ад таго, увайшоў карыстальнік у сыстэму (залагаваўся), ці не:

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

ReactDOM.render(
  // Паспрабуйце зьмяніць да isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

Паспрабуйце на CodePen.

Гэты прыклад рэндэрыць розныя прывітаньні, у залежнасьці ад значэньня ўласьцівасьці (prop) isLoggedIn.

Элемэнтныя зьменныя (Element Variables)

Вы можаце выкарыстоўваць зьменныя для захоўваньня элемэнтаў. Гэта можа дапамагчы вам умоўна рэндэрыць частку кампанэнта, у той час як астатняя частка выходных даных не зьмяняецца.

Разгледзім гэтыя два новыя кампанэнты, якія прадстаўляюць кнопкі Logout ды Login:

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login Залагавацца
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout Адлагавацца
    </button>
  );
}

У прыведзеным ніжэй прыкладзе мы створым кампанэнт са станам (stateful component), які называецца LoginControl.

Ён будзе рэндэрыць альбо <LoginButton />, альбо <LogoutButton />, у залежнасьці ад ягонага цякучага стану (state). Ён будзе таксама рэндэрыць <Greeting /> з папярэдняга прыкладу:

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;

    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

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

Паспрабуйце на CodePen.

Хоць аб’яўленьне зьменнай і выкарыстаньне апэратара if зьяўляецца выдатным спосабам для ўмоўнага рэндэрынгу кампанэнта, часам вы можаце захацець выкарыстаць больш кароткі сынтаксіс. Ніжэй разглядаецца некалькі спосабаў запісваць у радок умовы ў JSX.

Убудаваны If зь лягічным апэратарам &&

Вы можаце ўстаўляць любыя выразы ў JSX, абгортваючы іх у фігурныя дужкі, уключаючы JavaScript’аўскі лягічны апэратар &&. Гэта можа быць зручна для ўмоўнага ўключэньня элемэнта:

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello! Прывітаньне!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
          Вы маеце {unreadMessages.length} непрачытаных паведамленьняў.
        </h2>
      }
    </div>
  );
}

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

Паспрабуйце на CodePen.

Гэта працуе, таму што ў JavaScript, true && expression заўсёды мае значэньне expression, а false && expression заўсёды мае значэньне false.

Таму, калі ўмова true, то элемэнт, які адразу пасьля &&, зьявіцца на выхадзе. Калі яна false, то React праігнаруе й прапусьціць яго.

Убудаваны If-Else з умоўным апэратарам

Іншым мэтадам убудаваньня умоўнага рэндэрынгу элемэнтаў зьяўляецца ўмоўны апэратар JavaScript умова ? true : false.

У прыведзеным ніжэй прыкладзе мы выкарыстоўваем яго для ўмоўнага рэндэрынгу маленькага блёка тэксту.

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
      Карыстальнік <b>{isLoggedIn ? 'у цяперашні час' : 'не'}</b> залагаваны.
    </div>
  );
}

Ён таксама можа быць выкарыстаны для вялікіх выразаў, хаця пры гэтым менш відавочна, што адбываецца:

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

Гэтак жа, як і ў JavaScript, выбар адпаведнага стылю, заснаванага на тым, што вы й ваша каманда лічыце больш зручным для чытаньня, застаецца за вамі. Акрамя таго, памятайце, што кожны раз, калі ўмовы становяцца занадта складанымі, то гэта можа быць самы час, каб выцягнуць кампанэнт.

Прадухіленьне рэндэрынгу кампанэнта

У рэдкіх выпадках вы можаце схацець, каб кампанэнт схаваў сябе, нават калі ён рэндэраваўся іншым кампанэнтам. Каб зрабіць гэта, вяртайце null замест ягонага вываду рэндэрынгу.

У прыведзеным ніжэй прыкладзе <WarningBanner /> рэндэрыцца ў залежнасьці ад значэньня ўласьцівасьці (prop), якая называецца warn. Калі значэньне гэтай ўласьцівасьці (prop) — false, тады кампанэнт ня рэндэрыцца:

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')
);

Паспрабуйце на CodePen.

Вяртаньне null з мэтаду render кампанэнта ня ўплывае на запусканьне мэтадаў жыцьцёвага цыклу кампанэнта. Напрыклад, componentWillUpdate ды componentDidUpdate будуць выклікацца па-ранейшаму.