Условный рендеринг в React: способы и лучшие практики

О чём статья
В этой статье подробно рассмотрены основные способы условного рендеринга в React с примерами, типичные ошибки и рекомендации. Включены лучшие практики, чек-листы для ролей и небольшой decision-tree для выбора подхода.
Введение
Условный рендеринг — это изменение поведения интерфейса в зависимости от состояния приложения. Например, вы можете показывать разное приветствие днём и ночью, отображать кнопку “Войти” или “Выйти” в зависимости от статуса сессии, либо показывать лоадер до завершения загрузки данных.
Определение термина: условный рендеринг — вывод разных элементов (или их отсутствие) в JSX в зависимости от булевых выражений, значений состояния, пропсов или результатов вычислений.
Важно: при работе с условным рендерингом учитывайте особенности JavaScript (falsy-значения: 0, “”, null, undefined, false, NaN), чтобы не получить неожиданный вывод.
Основные способы условного рендеринга
1. Условные операторы if/else
Понятный и явно читаемый способ. Хорош для сложной логики, когда нужно вернуть разные компоненты целиком.
Пример:
function Dashboard(props) {
const { isLoggedIn } = props;
if (isLoggedIn) {
return ;
} else {
return ;
}
}Комментарий: этот вариант полезен, когда компонент либо полностью рендерится одним из двух способов, либо не рендерится вовсе.
2. Тернарный оператор
Короткий и удобный для вставки условного JSX внутри возвращаемого дерева. Подходит для двух альтернатив и когда результат небольшой.
Пример (исправленный и корректный синтаксис):
function Dashboard(props) {
const { isLoggedIn } = props;
return (
<>
{isLoggedIn ? : }
>
);
}Совет: не используйте вложенные тернарные операторы без явного форматирования — это ухудшает читаемость.
3. Переменные для JSX-элементов
Когда логика выбора более сложная, удобно подготовить переменную и вставить её в return.
Пример:
import React, { useState } from 'react';
function LoginBtn(props) {
return (
);
}
function LogoutBtn(props) {
return (
);
}
function Dashboard() {
const [loggedIn, setLoggedIn] = useState(true);
const handleLogin = () => setLoggedIn(true);
const handleLogout = () => setLoggedIn(false);
let button;
if (loggedIn) {
button = ;
} else {
button = ;
}
return (
<>
{button}
>
);
}Преимущество: компонент остаётся компактным, а логика выбора выделена в читаемый кусок.
4. Логические операторы (&& и ||)
Оператор && полезен, когда нужно рендерить элемент только если условие true. Оператор || часто используется для отображения запасного варианта.
Пример с уведомлениями (переведённые строки):
function ShowNotifications(props) {
const { notifications } = props; // массив
return (
<>
{notifications.length > 0 && (
У вас {notifications.length} уведомлений.
)}
>
);
}Пример с запасным вариантом (тернарный вариант надёжнее):
function ShowNotifications(props) {
const { notifications } = props;
return (
<>
{notifications.length > 0 ? (
У вас {notifications.length} уведомлений.
) : (
У вас нет уведомлений
)}
>
);
}Внимание: не используйте цепочки вида expr && A || B, это легко привести к непредсказуемому поведению и снижает читаемость.
Как предотвратить отрисовку компонента
Если нужно совсем ничего не рендерить, возвращайте null вместо JSX. React не будет выводить ничего в DOM.
Пример:
function Warning(props) {
const { warningMessage } = props;
if (!warningMessage) {
return null;
}
return (
<>
>
);
}Использование:
// кнопка будет отображаться
// ничего не будет рендеритьсяПримеры из реальной жизни
Рендеринг данных из API: учёт загрузки и ошибок
При асинхронной загрузке обязательно обрабатывайте состояния loading / error / success, иначе вы получите обращение к undefined. Ниже — практический пример с Axios и useEffect.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function FetchData() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const apiURL = 'https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY';
useEffect(() => {
let isMounted = true; // защита от setState после unmount
const fetchData = async () => {
try {
const response = await axios.get(apiURL);
if (isMounted) {
setData(response.data);
}
} catch (err) {
if (isMounted) setError(err.message || 'Ошибка загрузки');
} finally {
if (isMounted) setLoading(false);
}
};
fetchData();
return () => { isMounted = false; };
}, []);
if (loading) return Загрузка...
;
if (error) return Ошибка: {error}
;
return (
<>
Астрономическое фото дня
{data && (
<>
{data.title}
{data.explanation}
>
)}
>
);
}Примечание: всегда учитывайте unmount при асинхронных операциях, чтобы избежать обновления состояния у размонтированных компонентов.
Отображение ошибок в формах
Пример правильного условного показа ошибок:
function EmailField() {
const [error, setError] = useState(null);
// валидация и установка ошибки где-то в коде
return (
<>
{error && Произошла ошибка: {error}
}
>
);
}Важно: не используйте if внутри JSX (например, “{ if (error) { … } }”), это синтаксически некорректно. Для условной логики применяйте тернар, && или выносите в переменные.
Когда условный рендеринг подводит
- Если вы полагаетесь на && с числовыми значениями: 0 считается falsy и не отобразится. Для чисел лучше использовать тернар.
- Слишком много ветвлений в одном компоненте делает код трудным для тестирования. Выделяйте подкомпоненты.
- Если условия зависят от нескольких флагов — подумайте об использовании state machine (например, xstate) для явного управления состояниями.
Альтернативные подходы
- State machine (машины состояний): подходит для сложных переходов и многих состояний.
- Higher-Order Components / Render Props / Custom Hooks: вынос повторяющейся логики из UI.
- Композиция компонентов: стратегия «сложение маленьких компонентов» чаще приводит к более простому условному рендерингу.
Модель мышления (mental model)
Думайте об условном рендеринге как о переключателе сцен в театре:
- Состояние приложения — это сценарий.
- Компоненты — декорации и актёры, которые появляются или скрываются в зависимости от сценария.
Такой подход помогает разделять обязанности и избегать «глобального if» внутри большого JSX-дерева.
Рекомендации и лучшие практики
- Выносите сложную логику из JSX в функции или переменные.
- Используйте тернар для простых альтернатив; if/else — для больших разветвлений.
- Обрабатывайте явно loading и error состояния при работе с API.
- Учтите accessibility: при скрытии элементов используйте aria-атрибуты, если элемент просто скрывается стилем, а не удаляется из DOM.
- Пишите тесты для ключевых ветвей рендеринга.
Важно: если вы удаляете элемент из DOM (return null), вспомните о чистке таймеров и слушателей в useEffect.
Критерии приёмки
- Все пользовательские сценарии рендерятся корректно: loading, success, empty, error.
- Нет обращений к undefined при любых комбинациях пропсов и state.
- Компонент покрыт unit-тестами для каждой важной ветви рендеринга.
- Производительность: отсутствуют лишние перерендеры (проверено React DevTools).
Чек-листы по ролям
Разработчик:
- Выделил логику в функции/hooks.
- Обработал loading/error/empty состояния.
- Покрыл кейсы тестами.
Код-ревьювер:
- Нет побочных эффектов в render().
- Нет вложенных тернаров без комментариев.
- Accessibility и ARIA проверены.
PM / Продакт:
- Все пользовательские сценарии описаны.
- Пограничные состояния учтены (нет данных, медленный интернет, ошибка API).
Decision tree для выбора подхода
flowchart TD
A[Нужна простая альтернатива в JSX?] -->|Да| B[Тернар]
A -->|Нет| C[Сложная логика или много состояний]
C --> D{Нужно управлять множеством переходов?}
D -->|Да| E[State machine]
D -->|Нет| F[if/else или переменные с JSX]
B --> G[Хорошо для 2 вариантов]
F --> G
E --> GНебольшая методология (mini-method)
- Определите все возможные состояния (список: loading, success, empty, error, unauthorized и т. п.).
- Для каждого состояния опишите, что должен увидеть пользователь.
- Выделите общие части UI в подкомпоненты.
- Выберите технику условного рендеринга, руководствуясь компактностью и читаемостью.
- Добавьте тесты и проверку accessibility.
Доступность и безопасность
- При скрытии контента убедитесь, что вспомогательные технологии (скринридеры) получают необходимую информацию: если элемент важен — удаляйте из DOM, если нет — используйте aria-hidden.
- Не вставляйте небезопасный HTML через dangerouslySetInnerHTML без валидации.
Краткое резюме
Условный рендеринг — важный навык при создании интерактивных интерфейсов в React. Используйте if/else для сложной логики, тернарный оператор для простых замен, && для условного отображения и возвращайте null, если компонент не должен рендериться. Всегда учитывайте loading и error состояния при работе с асинхронными данными и помните про falsy-значения в JavaScript.
Важно: выбирайте подход, который делает код понятным коллегам и надёжным в граничных состояниях.
Дополнительные ресурсы: документация React (раздел о рендеринге), статьи по state machines, гайды по accessibility.
Похожие материалы
lsblk в Linux — обзор и примеры команд
Стриминговые приложения на PS4 — как установить
Сменить пароль root в Kali Linux
Как пожаловаться в Twitter — пошаговое руководство
Открыть ISO, TAR и 7‑Zip на Chromebook