Условная обработка в React и отрисовка списков без сложных решений
Явные ветки, стабильные ключи списка и шаблоны, которые сохраняют читаемость условной логики интерфейса, когда компоненты в производственных React-приложениях становятся сложнее простых примеров.
В этом руководстве воссоздаётся рабочий подход к условной отрисовке в React и отрисовке списков, а также к пониманию истинной природы свойства key. Акцент делается на контрактах, проверках и коде, который можно просто добавить в репозиторий без необходимости угадывать его назначение. Для обзора определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее видимость данных предотвращает неожиданные счёты в общих средах.
Условная отрисовка — показывать или не показывать
Для условной отрисовки — чтобы определить, показывать элемент или нет, необходимо заранее задать входные данные, ответственного за выполнение шага и критерии завершения, прежде чем изменять код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять. Размещайте типы рядом с компонентами и ограничивайте количество свойств. Чрезмерное количество свойств приводит к проблемам, которых должен был предотвратить TypeScript.
Подход 1 — Разветвление с использованием if, и возврат null при отсутствии отрисовки
Для подхода 1 — ветвление с использованием if, при этом возвращается null, когда ничего не рисуется. Перед изменением кода необходимо определить входные данные, ответственного за шаг и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.
Необходимо задокументировать как успешный, так и восстановительный пути выполнения. Повторные попытки и обработка некорректных сообщений являются частью продукта.
Размещайте типы рядом с компонентами и ограничивайте количество свойств. Чрезмерное количество свойств приводит к проблемам, которых TypeScript предназначен избегать.
type Props = { isInStock: boolean };
function StockBadge({ isInStock }: Props) {
if (!isInStock) {
return null; // out of stock — draw nothing
}
return <span className="badge">In stock</span>;
}
Подход 2 — один из двух вариантов с использованием тернарного оператора
Для подхода 2 — одного из двух с использованием тернарного оператора — необходимо определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Предпочтительнее использовать небольшие, тестируемые единицы вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину. Размещайте типы рядом с компонентами и ограничивайте количество свойств. Чрезмерное количество свойств приводит к проблемам, которых должен был избежать TypeScript. Для подхода 2 — одного из двух с использованием тернарного оператора — необходимо определить входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отображение информации предотвращает неожиданные расходы в совместных средах.
function StockBadge({ isInStock }: Props) {
return (
<span className="badge">
{isInStock ? 'In stock' : 'Out of stock'}
</span>
);
}
Подход 3 — «Только тогда», когда используется &&
При применении подхода 3 — «Только тогда», когда используется && — необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.
Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, доступном для аудита операторами.
Лучше использовать явную условную отрисовку, чем умные сокращения, скрывающие ошибки в производственной среде.
function Cart({ count }: { count: number }) {
return (
<div>
<h2>Cart</h2>
{count > 0 && <p>Items in cart: {count}</p>}
</div>
);
}
Самая распространённая ловушка с && — число 0
Чтобы избежать наиболее распространённой ловушки с && — числом 0, необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.
Необходимо одновременно задокументировать успешный сценарий работы и сценарий восстановления. Повторные попытки и обработка некорректных сообщений являются частью продукта.
Лучше использовать явную условную отрисовку, чем умные сокращения, скрывающие ошибки в производственной среде.
function Cart({ count }: { count: number }) {
return (
<div>
<h2>Cart</h2>
{/* 🔴 trap: if count is 0, "0" shows up on screen */}
{count && <p>Items in cart: {count}</p>}
</div>
);
}
function App() {
return (
<>
<Cart count={0} />
<Cart count={10} />
</>
);
}
export default App;
// ✅ count > 0 is true/false, so it's safe
{count > 0 && <p>Items in cart: {count}</p>}
Отрисовка списка — построение массива в цикле
Для отрисовки списков — построения массива в цикле — определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину. Лучше использовать явное условное отображение, чем умные сокращения, скрывающие ошибки в продакшене. Для отрисовки списков — построения массива в цикле — определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее видимость проблем предотвращает неожиданные счета в общих средах.
type Product = {
id: number;
name: string;
price: number;
};
const products: Product[] = [
{ id: 1, name: 'Mechanical Keyboard', price: 89000 },
{ id: 2, name: 'Wireless Mouse', price: 45000 },
{ id: 3, name: 'USB Hub', price: 23000 },
];
function ProductList() {
return (
<ul>
{products.map((product) => (
<li key={product.id}>
{product.name} — {product.price.toLocaleString()} won
</li>
))}
</ul>
);
}
key — тег с именем, который React использует для различения элементов
Для ключей — тегов имен, которые React использует для различения элементов, необходимо определить параметры ввода, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, доступном для аудита операторами. Списки ключей должны содержать стабильные бизнес-идентификаторы, а не индексы массивов, когда порядок может меняться.
Warning: Each child in a list should have a unique "key" prop.
Ключи должны быть «стабильными и уникальными»
Чтобы ключи были «стабильными и уникальными», необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки и обработка некорректных сообщений являются частью продукта. Списки ключей должны содержать стабильные бизнес-идентификаторы, а не индексы массивов, особенно когда порядок элементов может меняться.
<li key={product.id}> // ✅ each product's unique id — stable
Ловушка — не использовать индексы массива в качестве ключей
Для Trap: не используйте индексы массива в качестве ключей. Определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть однозначно определена. Списки ключей должны представлять собой стабильные бизнес-идентификаторы, а не индексы массива, особенно когда порядок элементов может меняться. Для Trap: не используйте индексы массива в качестве ключей. Определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отображение информации предотвращает неожиданные счета в общих средах.
// 🔴 common but dangerous pattern
{products.map((product, index) => (
<li key={index}>{product.name}</li>
))}
Совмещение элементов — условия + списки
Чтобы всё собрать вместе — условия и списки: определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, доступном для аудита операторами. Размещайте типы рядом с компонентами и ограничивайте количество свойств. Большое количество свойств приводит к проблемам, которых должен был избежать TypeScript.
type Product = {
id: number;
name: string;
price: number;
inStock: boolean;
};
function ProductList({ products }: { products: Product[] }) {
// when the list is empty — conditional rendering
if (products.length === 0) {
return <p>No products to display.</p>;
}
return (
<ul>
{products.map((product) => (
<li key={product.id}>
{product.name} — {product.price.toLocaleString()} won
{/* badge only when out of stock — && (safe since the left side is boolean) */}
{!product.inStock && <span className="badge"> (Out of stock)</span>}
</li>
))}
</ul>
);
}
// dummy data — swap in an empty array [] to see the "No products" message
const products: Product[] = [
{ id: 1, name: 'Mechanical Keyboard', price: 89000, inStock: true },
{ id: 2, name: 'Wireless Mouse', price: 42000, inStock: false },
{ id: 3, name: 'USB-C Hub', price: 35000, inStock: true },
];
function App() {
return <ProductList products={products} />;
}
Заключение
В заключение определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки и обработка некорректных сообщений являются частью продукта. Размещайте типы рядом с компонентами и ограничивайте количество свойств. Чрезмерное количество свойств приводит к проблемам, которых TypeScript предназначен избегать.
Ссылки
Для справки: определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину. Размещайте типы рядом с компонентами и ограничивайте количество передаваемых параметров. Чрезмерное количество параметров приводит к проблемам, которых должен предотвращать TypeScript. Для справки: определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отслеживание помогает избежать неожиданных расходов в совместных средах.
Чек-лист операций
Для операционного чек-листа необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность повторно выполнить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние.
Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия элементов, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи.
Предпочитайте явную условную обработку данных вместо умных схем прерывания выполнения, которые скрывают ошибки в производственной среде.
Даёте приоритет надёжности перед красивыми одноразовыми демонстрациями.
Записывайте время выполнения и затраты рядом с функциональными результатами. Ранняя видимость данных предотвращает неожиданные счёты в общих средах.
Предпочитайте явную условную обработку данных вместо умных схем прерывания выполнения, которые скрывают ошибки в производственной среде.
Перед внедрением стека необходимо заморозить версии, сделать копию «золотого» варианта кода для критической части работы и уточнить шаги возврата к предыдущему состоянию. В совместных средах требуются ограничения на скорость работы, проверки принадлежности ресурсов и четко определенный ответственный за обновление секретов.