Перейти к содержанию

Фрагменты

Возврат нескольких элементов из компонента является распространённой практикой в React. Фрагменты позволяют формировать список дочерних элементов, не создавая лишних узлов в DOM.

1
2
3
4
5
6
7
8
9
render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

Также существует сокращённая запись, однако не все популярные инструменты поддерживают её.

Мотивация

Возврат списка дочерних элементов из компонента – распространённая практика. Рассмотрим пример на React:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Table extends React.Component {
    render() {
        return (
            <table>
                <tr>
                    <Columns />
                </tr>
            </table>
        );
    }
}

<Columns /> должен вернуть несколько элементов <td>, чтобы HTML получился валидным. Если использовать div как родительский элемент внутри метода render() компонента <Columns />, то HTML окажется невалидным.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Columns extends React.Component {
    render() {
        return (
            <div>
                <td>Привет</td>
                <td>Мир</td>
            </div>
        );
    }
}

Результатом вывода <Table /> будет:

1
2
3
4
5
6
7
8
<table>
    <tr>
        <div>
            <td>Привет</td>
            <td>Мир</td>
        </div>
    </tr>
</table>

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

Использование

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Columns extends React.Component {
    render() {
        return (
            <React.Fragment>
                <td>Привет</td>
                <td>Мир</td>
            </React.Fragment>
        );
    }
}

Результатом будет правильный вывод <Table />:

1
2
3
4
5
6
<table>
    <tr>
        <td>Привет</td>
        <td>Мир</td>
    </tr>
</table>

Сокращённая запись

Существует сокращённая запись объявления фрагментов. Она выглядит как пустые теги:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Columns extends React.Component {
    render() {
        return (
            <>
                <td>Привет</td>
                <td>Мир</td>
            </>
        );
    }
}

Можно использовать &lt;&gt;&lt;/&gt; так же, как используется любой другой элемент. Однако такая запись не поддерживает ключи или атрибуты.

Обратите внимание, что большинство инструментов ещё не поддерживают сокращённую запись, поэтому можно явно указывать <React.Fragment>, пока не появится поддержка.

Фрагменты с ключами

Фрагменты, объявленные с помощью <React.Fragment>, могут иметь ключи. Например, их можно использовать при создании списка определений, преобразовав коллекцию в массив фрагментов.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function Glossary(props) {
    return (
        <dl>
            {props.items.map((item) => (
                // Без указания атрибута `key`, React выдаст предупреждение об его отсутствии
                <React.Fragment key={item.id}>
                    <dt>{item.term}</dt>
                    <dd>{item.description}</dd>
                </React.Fragment>
            ))}
        </dl>
    );
}

key – это единственный атрибут, допустимый у Fragment. В будущем мы планируем добавить поддержку дополнительных атрибутов, например, обработчиков событий.

Живой пример

Новый синтаксис JSX фрагментов можно попробовать на CodePen.

Комментарии