Условный рендеринг в React

ReactBeginner
Практиковаться сейчас

Введение

В React условный рендеринг (conditional rendering) — это ключевая концепция, позволяющая отображать различные компоненты или элементы в зависимости от определенных условий или состояния приложения. Это фундаментально для создания динамических и отзывчивых пользовательских интерфейсов. Например, вы можете захотеть показать кнопку "Войти" (Log In) гостю, но страницу "Профиль" (Profile) авторизованному пользователю.

В этой лабораторной работе вы изучите несколько распространенных техник реализации условного рендеринга в ваших React-приложениях. Мы начнем с базовой настройки проекта и постепенно рассмотрим различные методы, включая:

  • Тернарный оператор (? :) для простой логики if-else.
  • Логический оператор && для рендеринга элемента только тогда, когда условие истинно.
  • Использование переменных для хранения элементов для более чистого JSX.
  • Возврат null для предотвращения рендеринга компонента.
  • Использование состояния React (React state) для создания интерактивных пользовательских интерфейсов, которые изменяют отображаемое содержимое.

К концу этой лабораторной работы вы получите твердое понимание того, как управлять тем, что видят ваши пользователи, в зависимости от состояния вашего приложения.

Используйте тернарный оператор в JSX для условия

На этом шаге вы научитесь использовать условный (тернарный) оператор (? :) для инлайн-логики if-else непосредственно в вашем JSX. Это лаконичный способ выбора между двумя различными UI-элементами для рендеринга.

Сначала перейдем в каталог нашего проекта. Все команды должны выполняться из этого каталога.

cd ~/project/my-app

Далее нам нужно установить зависимости проекта.

npm install

Теперь давайте изменим основной компонент приложения. Откройте файл src/App.jsx в файловом проводнике слева. Мы создадим компонент Greeting, который будет отображать разное сообщение в зависимости от того, авторизован ли пользователь.

Замените все содержимое файла src/App.jsx следующим кодом:

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  return (
    <div>{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}</div>
  );
}

function App() {
  return (
    <div>
      {/* Попробуйте изменить isLoggedIn на false, чтобы увидеть другое сообщение! */}
      <Greeting isLoggedIn={true} />
    </div>
  );
}

export default App;

В компоненте Greeting выражение {isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>} проверяет значение свойства isLoggedIn. Если оно равно true, рендерится сообщение "Welcome back!". В противном случае рендерится сообщение "Please sign up.".

Теперь запустим сервер разработки, чтобы увидеть наш компонент в действии.

npm run dev -- --host 0.0.0.0 --port 8080

После запуска сервера откройте вкладку Web 8080 в верхней части экрана. Вы должны увидеть сообщение "Welcome back!". Вы можете попробовать изменить isLoggedIn={true} на isLoggedIn={false} в файле src/App.jsx, сохранить файл и наблюдать, как содержимое автоматически обновляется в браузере.

Примените логический оператор && для короткого замыкания

На этом шаге мы рассмотрим еще один распространенный шаблон условного рендеринга: логический оператор &&. Он особенно полезен, когда вы хотите отобразить элемент только в том случае, если определенное условие истинно, и ничего не отображать в противном случае. В JavaScript выражение true && expression всегда вычисляется как expression, а false && expression всегда вычисляется как false. React обрабатывает false как значение, которое ничего не рендерит.

Давайте изменим наш файл src/App.jsx, чтобы продемонстрировать это. Мы добавим компонент, который показывает количество уведомлений только при наличии непрочитанных сообщений.

Оставьте сервер разработки запущенным. Вам нужно только отредактировать файл и сохранить его, чтобы увидеть изменения.

Замените содержимое файла src/App.jsx следующим кодом:

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 && (
        <h2>You have {unreadMessages.length} unread messages.</h2>
      )}
    </div>
  );
}

function App() {
  const messages = ["React", "Re: React", "Re:Re: React"];
  // Попробуйте изменить messages на пустой массив: const messages = [];
  return <Mailbox unreadMessages={messages} />;
}

export default App;

В этом примере элемент <h2> рендерится только потому, что условие unreadMessages.length > 0 истинно. Если вы измените массив messages в компоненте App на пустой (const messages = [];), условие станет ложным, и элемент <h2> не будет отрендерен.

После сохранения файла проверьте вкладку Web 8080. Вы должны увидеть сообщение "You have 3 unread messages.".

Храните условие в переменной и отображайте, если истина

На этом шаге вы научитесь делать ваши компоненты более чистыми, подготавливая контент в переменной перед оператором return. Этот подход очень полезен, когда условная логика становится более сложной, чем та, с которой могут изящно справиться тернарный оператор или оператор &&.

Используя переменную, вы можете применять стандартные операторы if JavaScript для определения того, что должен рендерить компонент.

Давайте обновим файл src/App.jsx, чтобы использовать этот метод. Мы создадим компонент, который отображает кнопку "Login" или "Logout" в зависимости от свойства (prop).

Замените содержимое файла src/App.jsx следующим кодом:

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

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

function LoginControl(props) {
  const isLoggedIn = props.isLoggedIn;
  let button;

  if (isLoggedIn) {
    button = <LogoutButton />;
  } else {
    button = <LoginButton />;
  }

  return (
    <div>
      The user is <b>{isLoggedIn ? "currently" : "not"}</b> logged in.
      {button}
    </div>
  );
}

function App() {
  return <LoginControl isLoggedIn={false} />;
}

export default App;

В компоненте LoginControl мы объявляем переменную button. Затем оператор if присваивает ей либо <LoginButton />, либо <LogoutButton />. Наконец, JSX в операторе return просто включает {button}. Это отделяет логику рендеринга и упрощает чтение оператора return.

Сохраните файл и наблюдайте за изменениями на вкладке Web 8080. Вы должны увидеть кнопку "Login". Попробуйте изменить isLoggedIn={false} на isLoggedIn={true}, чтобы увидеть вместо нее кнопку "Logout".

Возвращайте null или пустой фрагмент, если условие ложно

На этом шаге мы рассмотрим сценарий, когда вы хотите полностью предотвратить рендеринг компонента. Вы можете добиться этого, заставив компонент возвращать null или пустой фрагмент (<></>).

Это распространенный шаблон для компонентов, которые должны быть видимы только при определенных условиях. Например, баннер с предупреждением, который должен появляться только при наличии фактического предупреждения.

Давайте изменим src/App.jsx, чтобы включить компонент WarningBanner, который рендерится только тогда, когда свойство (prop) warn имеет значение true.

Замените содержимое файла src/App.jsx следующим кодом:

function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    <div style={{ backgroundColor: "yellow", padding: "10px", color: "black" }}>
      Warning!
    </div>
  );
}

function App() {
  // Попробуйте изменить это на false, чтобы скрыть баннер
  const showWarning = true;

  return (
    <div>
      <WarningBanner warn={showWarning} />
      <p>This is the main content of the page.</p>
    </div>
  );
}

export default App;

В компоненте WarningBanner мы проверяем свойство warn в начале. Если оно равно false, компонент немедленно возвращает null, и React ничего для него не рендерит. Если оно равно true, он продолжает возвращать div с предупреждением.

После сохранения файла проверьте вкладку Web 8080. Вы увидите желтый баннер с предупреждением. Теперь вернитесь в src/App.jsx, измените const showWarning = true; на const showWarning = false; и сохраните. Баннер исчезнет со страницы.

Переключайте состояние для изменения условного отображения

На этом заключительном шаге мы объединим условный рендеринг с состоянием React для создания интерактивного компонента. До сих пор наши условия основывались на свойствах (props). Используя состояние, мы можем изменять вывод компонента в ответ на действия пользователя, такие как нажатие кнопки.

Мы будем использовать хук useState для управления состоянием компонента.

Давайте изменим src/App.jsx, чтобы создать компонент LoginControl, который управляет собственным состоянием isLoggedIn и позволяет пользователю его переключать.

Сначала вам нужно импортировать useState из React. Замените содержимое файла src/App.jsx следующим кодом:

import { useState } from "react";

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  }
  return <h1>Please sign up.</h1>;
}

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

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

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const handleLoginClick = () => {
    setIsLoggedIn(true);
  };

  const handleLogoutClick = () => {
    setIsLoggedIn(false);
  };

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

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

export default App;

Вот что происходит:

  1. import { useState } from 'react'; импортирует хук useState.
  2. const [isLoggedIn, setIsLoggedIn] = useState(false); инициализирует переменную состояния isLoggedIn значением false. setIsLoggedIn — это функция, которую мы используем для обновления этого состояния.
  3. Мы определяем функции handleLoginClick и handleLogoutClick, которые вызывают setIsLoggedIn для обновления состояния.
  4. Компонентам LoginButton и LogoutButton передается соответствующая функция-обработчик через их свойство onClick.
  5. Компонент Greeting и переменная button зависят от состояния isLoggedIn, поэтому они будут перерисовываться при каждом изменении состояния.

Сохраните файл и перейдите на вкладку Web 8080. Вы увидите сообщение "Please sign up." и кнопку "Login". Нажмите кнопку "Login". Состояние обновится, и пользовательский интерфейс изменится, показывая "Welcome back!" и кнопку "Logout".

Резюме

Поздравляем с завершением этой лабораторной работы по условному рендерингу в React! Вы изучили и отработали наиболее распространенные методы управления отображением вашего приложения в зависимости от различных условий.

В этой лабораторной работе вы рассмотрели:

  • Использование тернарного оператора (? :) для простой встроенной логики if-else.
  • Применение логического оператора && для рендеринга элемента только при выполнении условия.
  • Сохранение JSX в переменной для обработки более сложной логики с помощью операторов if, чтобы сохранить чистоту оператора return.
  • Возврат null из компонента, чтобы предотвратить его рендеринг.
  • Комбинирование этих методов с хуком useState для создания динамических и интерактивных пользовательских интерфейсов, реагирующих на действия пользователя.

Эти шаблоны являются фундаментальными строительными блоками практически любого приложения React. Освоение их позволит вам создавать богатые, отзывчивые и удобные для пользователя интерфейсы.