React Fragments за 5 минут (с примерами)

И вы думаете про себя: «О Боже, что я опять сделал не так?».

Но к счастью для вас (и для всех нас — разработчиков React), на этот раз проблема очень проста.

Давайте посмотрим на код, который вызвал проблему.

import React from "react";

const Fragment = () => {
  return 
  <div>Fragments</div>
  <p>in React</p>
  ;
};

export default Fragment;
Вход в полноэкранный режим Выход из полноэкранного режима

Как вы можете видеть, мы пытаемся вернуть два JSX-элемента из нашего компонента Fragment.

И, как вы, вероятно, понимаете, это и есть корень нашей проблемы.

Итак, почему?

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

И вы правы — это распространенный паттерн в React.

Но вы должны помнить:

Компонент должен возвращать только один родительский элемент, не больше и не меньше.


Что мы можем с этим сделать?

Одно из решений — обернуть его в элемент «div».

Давайте посмотрим, работает это или нет!

import React from "react";

const Fragment = () => {
  return (
    <div className="wrapper">
      <p>Fragments</p>
      <p>in React</p>
    </div>
  );
};

export default Fragment;
Вход в полноэкранный режим Выход из полноэкранного режима

Ура! Это сработало!

Но является ли это лучшим решением?

Нет!

Есть несколько проблем, которые с ним связаны.

Во-первых, мы добавляем дополнительный узел в DOM. Он занимает дополнительное место в памяти.

Во-вторых, это просто неважно. Он нужен нам только для того, чтобы работал наш JSX. Немного нелепо, правда?

И в дополнение к этому, иногда эта обертка div может даже нарушить нашу верстку и привести к отображению недопустимого HTML!

Вы, наверное, думаете, как этот невинный div может сломать ваш HTML?

Позвольте мне показать вам быстрый пример, который продемонстрирует это!

Представим, что мы хотим отобразить таблицу.
Поэтому мы определяем элементы «table», «tbody», «tr».

import Fragment from "./fragment";

function App() {
  return (
    <div className="App">
      <table>
        <tbody>
          <tr>
            <Fragment />
          </tr>
        </tbody>
      </table>
    </div>
  );
}

export default App
Вход в полноэкранный режим Выход из полноэкранного режима

И, допустим, мы хотим отдельный компонент для ячеек с данными (элементы «td»).

import React from "react";

const Fragment = () => {
  return (
    <div className="wrapper">
      <td>Team </td>
      <td>Points</td>
      <td> Wins</td>
    </div>
  );
};

export default Fragment;
Войдите в полноэкранный режим Выход из полноэкранного режима

Мы уже знаем, что мы не можем возвращать несколько значений из компонента.

Поэтому мы обернем наши элементы «td» в div с классом «wrapper» (стили к этому классу не применяются, просто для демонстрации).

Теперь давайте проверим, работает это или нет!

Кажется, что работает, но черт…
Посмотрите на консоль …

Мы не можем поместить «td» внутрь div.
И «tr» не может содержать элемент div.

Q.E.D.


Итак, что мы должны сделать вместо этого?

Вы правильно догадались — мы можем использовать фрагменты!

Фрагмент — это просто синтаксис, который позволяет вам группировать список дочерних элементов (как это сделал наш div), но…

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

Хорошо, это звучит как беспроигрышный вариант, верно?

Как его использовать?

Довольно просто!

import React from "react";

const Fragment = () => {
  return (
    <React.Fragment>
      <p>Fragments</p>
      <p>in React</p>
    </React.Fragment>
  );
};

export default Fragment;
Войти в полноэкранный режим Выйти из полноэкранного режима

Все, что нам нужно сделать, это использовать React.Fragment вместо div.

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

import React from "react";

const Fragment = () => {
  return (
    <>
      <p>Fragments</p>
      <p>in React</p>
    </>
  );
};

export default Fragment;
Вход в полноэкранный режим Выйти из полноэкранного режима

Оба этих примера кода приведут к такому DOM:

Как видите, никаких дополнительных JSX-элементов в DOM добавлено не было!

Есть ли разница между React.Fragment и коротким синтаксисом?

На самом деле, есть одно небольшое отличие.

Посмотрите на этот фрагмент кода:

import React from "react";

const Fragment = () => {
  const arrayOfNumbers = [1, 2, 3, 4, 5];
  return arrayOfNumbers.map((number, index) => (
    <>
      <p>{number}</p>
      <p>{index}</p>
    </>
  ));
};

export default Fragment;
Вход в полноэкранный режим Выход из полноэкранного режима

Мы перебираем массив и для каждого элемента возвращаем 2 абзаца (само значение и его индекс).

Мы помещаем эти абзацы в пустой тег (короткий синтаксис React.Fragment).

Все работает хорошо, но …
Мы получили эту ошибку в консоли …

Если вы читали мой предыдущий пост о ключах React, вы знаете, что это такое и как с этим работать.
Если нет, посмотрите!

Итак, как вы понимаете, нам нужно добавить ключ к нашему родительскому элементу.

И здесь возникает проблема.

Мы не можем сделать это с помощью короткого синтаксиса React.Fragment.

Вместо этого мы должны использовать React.Fragment и дать ему атрибут key.

import React from "react";

const Fragment = () => {
  const arrayOfNumbers = [1, 2, 3, 4, 5];
  return arrayOfNumbers.map((number, index) => (
    <React.Fragment key={index}>
      <p>{number}</p>
      <p>{index}</p>
    </React.Fragment>
  ));
};

export default Fragment;
Вход в полноэкранный режим Выход из полноэкранного режима


Краткое заключение:

Фрагменты можно использовать всякий раз, когда вам нужно вернуть несколько JSX-элементов из компонента.
Вы должны использовать их вместо того, чтобы обернуть все в div, потому что React.Fragment не добавляет дополнительный узел в DOM. Существует 2 его формы: полный и короткий синтаксис.
Единственная разница между ними в том, что в коротком синтаксисе вы не можете использовать атрибут key (если он вам нужен).


Вот и все, ребята.

Я надеюсь, что сегодня вы узнали что-то новое!
Я буду благодарен, если вам понравится этот пост или вы оставите комментарий ниже!

Также, не стесняйтесь следовать за мной на GitHub и Medium!

Adios, mi amigos)

Оцените статью
Procodings.ru
Добавить комментарий