Как избежать лишнего обертывания <div> в React?


114

Сегодня я начал изучать ReactJS и через час столкнулся с проблемой ... Я хочу вставить компонент, который имеет две строки внутри div на странице. Упрощенный пример того, что я делаю ниже.

У меня есть html:

<html>
..
  <div id="component-placeholder"></div>
..
</html>

Функция рендеринга выглядит так:

...
render: function() {

    return(
        <div className="DeadSimpleComponent">
            <div className="DeadSimpleComponent__time">10:23:12</div >
            <div className="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
        </div>
    )
}
....

А ниже я вызываю рендер:

ReactDOM.render(<DeadSimpleComponent/>, document.getElementById('component-placeholder'));

Сгенерированный HTML выглядит так:

<html>
..
  <div id="component-placeholder">
    <div class="DeadSimpleComponent">
            <div class="DeadSimpleComponent__time">10:23:12</div>
            <div class="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
    </div>
</div>
..
</html>

Проблема в том, что я не очень доволен тем, что React заставляет меня обернуть все в div "DeadSimpleComponent". Какое решение является лучшим и простым без явных манипуляций с DOM?

ОБНОВЛЕНИЕ 28.07.2017: Сопровождающие React добавили эту возможность в React 16 Beta 1

Начиная с React 16.2 , вы можете сделать это:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

4
идеальная практика нейминга ;-)
Кирилл Резников

Могу я увидеть ваш HTML-файл? Я неправильно прочитал ваш вопрос. Хотя у меня может быть обходной путь.
Louis93

Что-то вроде этого: jsfiddle.net/qawumm3v
Кирилл Резников

У вас проблема с компонентом, состоящим из одного элемента? В самом деле?
Доминик

Что вы имеете в виду? Я просто пробую React, это не должно быть очень сложно ... Но ограничение выглядит раздражающим.
Кирилл Резников

Ответы:


143

Это требование было удалено в React версии (16.0)] 1 , так что теперь вы можете избежать этой оболочки.

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

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

Подробнее здесь: Фрагменты


1
Отличные новости ДмитрийУльянец. Есть ли запланированная дата выхода?
Jonas Carlbaum

Он выпущен 26 сентября 2017 г., см. Responsejs.org/blog/2017/09/26/react-v16.0.html
Том

57

Обновление 2017-12-05: React v16.2.0 теперь полностью поддерживает рендеринг фрагментов с улучшенной поддержкой возврата нескольких дочерних элементов из метода рендеринга компонентов без указания ключей в дочерних элементах:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

Если вы используете версию React до v16.2.0, вместо нее также можно использовать <React.Fragment>...</React.Fragment>:

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

Оригинал:

React v16.0 представил возврат массива элементов в методе рендеринга без упаковки его в div: https://reactjs.org/blog/2017/09/26/react-v16.0.html

render() {
  // No need to wrap list items in an extra element!
  return [
    // Don't forget the keys :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

На данный момент ключ необходим для каждого элемента, чтобы избежать ключевого предупреждения, но это может быть изменено в будущих выпусках:

В будущем мы, вероятно, добавим в JSX специальный синтаксис фрагментов, не требующий ключей.


Новый сокращенный синтаксис <> </> великолепен. Однако у меня все еще есть много смешанных чувств по этому поводу.
Thulani Chivandikwa

@ThulaniChivandikwa Не могли бы вы высказать свои опасения по поводу сокращенного синтаксиса?
Том

1
Я думаю, что это больше связано с тем, что пустой тег в JSX является странным и не очень интуитивным, если вы точно не знаете, что он делает.
Thulani Chivandikwa


3

Используйте [] вместо (), чтобы обернуть весь возврат.

render: function() {
  return[
    <div className="DeadSimpleComponent__time">10:23:12</div >
    <div className="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
  ]
}


1

Это все еще необходимо , НО React теперь обязательно создает элементы без создания дополнительного элемента DOM.

Требуется дополнительная упаковка (обычно с родительским элементом div), потому что для createElementметода Reacts требуется typeпараметр, равный either a tag name string (such as 'div' or 'span'), a React component type (a class or a function). Но это было до того, как они представили React Fragment.

Обратитесь к этому НОВОМУ api doc для createElement

React.createElement : создать и вернуть новый элемент React заданного типа. Аргумент типа может быть строкой имени тега (например, 'div' или 'span'), типом компонента React (класс или функция) или типом фрагмента React .

вот официальный пример, Refer React.Fragment .

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}

0

Вы не сможете избавиться от этого divэлемента. React.render () должен вернуть один действительный узел DOM.


div игнорируются, Knockout.JS делает то же самое. наличие div без стиля на внешней части вашего компонента ничего не дает.
Крис Хоукс

16
@ChrisHawkes, не согласен. один div-обертка влияет на селекторы CSS.
Даунхиллски

При работе с семантическими элементами, которые вы не хотите быть полностью компонентами React, это становится проблемой. Допустим, есть тег раздела с элементами верхнего и нижнего колонтитула, а между ними есть контейнер карты Google, который мы не хотим использовать в React. Тогда было бы неплохо иметь заголовок в качестве компонента React и нижний колонтитул в качестве компонента React, без необходимости включать дополнительные div: s снаружи внутри компонентов React ... Это простой глупый дизайн, если вам вообще небезразличен html вы
выводите

0

Вот один из способов визуализации "прозрачных" компонентов:

import React from 'react'

const Show = (props) => {
  if (props.if || false) {
    return (<React.Fragment>{props.children}</React.Fragment>)
  }
  return '';
};

----


<Show if={yomama.so.biq}>
    <img src="https://yomama.so.biq">
    <h3>Yoamama</h3>
<Show>

введите описание изображения здесь


0

Также есть обходной путь. Приведенный ниже код блока генерирует фрагмент без необходимости React.Fragment.

return [1,2,3].map(i=>{
if(i===1) return <div key={i}>First item</div>
if(i===2) return <div key={i}>Second item</div>
return <div key={i}>Third item</div>
})

0

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

Кроме того, если вы хотите повеселиться, вы можете реализовать (и многому научиться) режим React, который удаляет лишние div, и для этого я действительно хочу поделиться отличным видео о том, как вы можете сделать это на самой базе кода реакции.

https://www.youtube.com/watch?v=aS41Y_eyNrU

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.