Головна / Статті / Умовне відображення та рендеринг списків у React без складних методів

Умовне відображення та рендеринг списків у React без складних методів

Явні гілки, стабільні ключі списку та шаблони, які зберігають читабельність умовної логіки інтерфейсу, коли компоненти у продакшн-додатках на React стають складнішими за прості приклади.

1963 слів

У цьому посібнику створюється функціональний підхід до: умовного відображення та відображення списків у 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 використовує для розрізнення елементів, необхідно визначити параметри введення, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функціоналу мають знаходитися в одному місці, яке можуть перевіряти оператори. Списки ключів мають бути стабільними бізнес-ID, а не індексами масиву, коли порядок може змінюватися.

Warning: Each child in a list should have a unique "key" prop.

Ключі мають бути „стабільними та унікальними“

Щоб ключі були «стабільними та унікальними», необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Необхідно документувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби та обробка некоректних повідомлень є частиною продукту. Списки ключів мають бути стабільними бізнес-ID, а не індексами масиву, якщо порядок може змінюватися.

<li key={product.id}>   // ✅ each product's unique id — stable

Підступ — не використовуйте індекс масиву як ключ

Для Trap: не використовуйте індекс масиву як ключ — спочатку визначте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність. Списки ключів мають бути стабільними бізнес-ID, а не індексами масиву, якщо порядок може змінюватися. Для 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. Для посилань визначайте вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не здогадуючись про прихований стан. Записуйте час виконання та витрати поруч із функціональними результатами. Рання видимість запобігає несподіваним рахункам у спільних середовищах.

Чек-лист операцій

Для контрольного списку операцій необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан.

Розглядайте цю стадію як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

Віддавайте перевагу чіткому умовному форматуванню перед хитромудрими способами обриву виконання, які приховують баги у продакшені.

Віддавайте перевагу надійності навіть за рахунок менш привабливих демонстрацій, а не хитромудрим одноразовим рішенням.

Записуйте час виконання та витрати поруч із функціональними результатами. Чітка відображуваність інформації заздалегідь запобігає несподіваним рахункам у спільних середовищах.

Віддавайте перевагу чіткому умовному форматуванню перед хитромудрими способами обриву виконання, які приховують баги у продакшені.

Перш ніж запускати стек, заморозьте версії, створіть «золотий» запис для критичного шляху та підтвердьте кроки відкату. У спільних середовищах необхідні обмеження швидкості, перевірки прав власності та чіткий власник для зміни секретів.