Почему фрагменты в React 16 лучше контейнерных элементов?

165

В Реакте 16.2 улучшенная поддержка Fragmentsбыла добавлена. Более подробную информацию можно найти в блоге React здесь.

Мы все знакомы со следующим кодом:

render() {
  return (
    // Extraneous div element :(
    <div>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </div>
  );
}

Да, нам нужен контейнерный div, но это не так уж важно.

В Реакте 16.2 мы можем сделать это, чтобы избежать окружающего контейнера div:

render() {
  return (
    <Fragment>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </Fragment>
  );
}

В любом случае нам все еще нужен контейнерный элемент, окружающий внутренние элементы.

Мой вопрос, почему использование Fragmentпредпочтительнее? Это помогает с производительностью? Если так, то почему? Хотелось бы немного понимания.

Макс Миллингтон
источник
2
Я считаю, что это действительно полезно для стиля flexbox при создании дочерних элементов первого уровня для родителя
willwoo
32
Проблема в divтом, что вам не всегда нужен элемент-обертка. Элементы обертки имеют значение, и обычно для удаления этого значения требуются дополнительные стили. <Fragment>это просто синтаксический сахар, который не отображается. Существуют ситуации, когда создание оболочки очень сложно, например, в SVG, где <div>его нельзя использовать, и <group>это не всегда то, что вам нужно.
Sulthan

Ответы:

305
  1. Это немного быстрее и требует меньше памяти (не нужно создавать дополнительный узел DOM). Это имеет реальную выгоду только на очень больших и / или глубоких деревьях, но производительность приложений часто страдает от гибели в тысячу сокращений. Это на одно сокращение меньше.
  2. Некоторые механизмы CSS, такие как Flexbox и CSS Grid, имеют особые отношения родитель-потомок, а добавление divs в середине затрудняет сохранение желаемого макета при извлечении логических компонентов.
  3. Инспектор DOM менее загружен. :-)

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

Дан Абрамов
источник
24
4. Написание списков определений <dt><dd>становится намного проще. Возвращение парных элементов было неудобно раньше Fragments.
Sonson123
Работают ли фрагменты по-родному? Я пытался import Fragment from 'react'. Но это не определено в RN.
binchik
3
Ведь number 2таблицы были для нас самой большой проблемой. Необходимая структура table>tr>td(возможно, с theadи аналогичные) сделаны для некоторого неудобного кода React.
Мацеманн
2
@binchik пробовал import {Fragment} from 'react'? это именной экспорт.
Соска
1
Номер 3 самый важный!
Зак Смит
28

Добавление всех ответов выше есть еще одно преимущества: читабельность кода , Fragmentкомпонент поддерживает синтаксическую форму сахара, <>. Таким образом, код в вашем вопросе может быть написан легче как:

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </>
  );
}

Согласно документам ,

В React это относится к <React.Fragment/>элементу, как в примере из предыдущего раздела. (Non-React-фреймворки, использующие JSX, могут компилироваться во что-то другое.)

Без помех, верно?

Обратите внимание, что вам все еще нужно использовать <Fragment>синтаксис, если вам нужно предоставить keyфрагмент.

датчанин
источник
Этот более короткий синтаксис в настоящее время еще не поддерживается в create-реагировать-приложение. Обратитесь по адресу
codingsplash
2
У @codingsplash CRA 2.0 есть это сейчас.
Познакомьтесь с Завери
1
Не выносит этот кусочек синтаксического сахара, он выглядит непреднамеренно и передает мало присущего ему смысла. Очень предпочитаю<Fragment>
ESR
3
@ESR лично мне это нравится. Подумай об этом так. Дети обернуты ничем, точно так же, как в <> ничего нет. Невидимый.
user3614030
6
  • Добавленные функции невозможны раньше с JSX
  • Лучшая семантическая разметка jsx. Элементы обертки используются при необходимости не потому, что они вынуждены.
  • Меньшая общая разметка dom (повышенная производительность рендеринга и меньшие затраты памяти)

Это так же просто, как когда вам не нужен элемент-обертка, вы не обязаны его использовать. Хорошо иметь меньше элементов, но я думаю, что наибольшим преимуществом является возможность отображать элементы в jsx, которые раньше были невозможны, и добавление лучшего семантического значения к элементам-оберткам, потому что они теперь являются необязательными.

Это было невозможно раньше:

 <select>
    {this.renderOptions()}
 </select>

Взглянув на следующее в React 15, вы не сможете определить, нужен ли элемент-обертка:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>
pllee
источник
2

В соответствии с документом activjs.org наиболее важными потребностями, <Fragment> </Fragment>а не div, являются недопущение нарушения семантики HTML. Когда мы используем div вместо <Fragment> </Fragment>мы нарушаем семантику HTML.

Чтобы узнать больше о семантике HTML. пожалуйста, нажмите, а также в некоторых случаях, если вы используете div вместо Fragments, это будет недействительным HTML, например, посмотрите на этот код:

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}

<table>
      <tr>
        <div>
          <td>Hello</td>
          <td>World</td>
        </div>
      </tr>
 </table>

Фрагменты решают эту проблему.

Сета Рам Ядав
источник
1
  1. Используя <React.Fragment>...</React.Fragment>, мы можем добавить родительский тег к нашим элементам JSX без добавления дополнительного узла в DOM.
  2. Вы можете заменить дополнительные теги div на React.Fragment.
  3. писать React.Fragment каждый раз слишком долго для вас. React.Fragment имеет сокращенный синтаксис, который вы можете использовать. это<>...</>.
Hemant
источник