Jak uniknąć dodatkowego zawijania <div> w Reakcie?

114

Dzisiaj zacząłem uczyć się ReactJS i po godzinie napotkałem problem ... Chcę wstawić na stronie komponent, który ma dwa wiersze w div. Poniżej uproszczony przykład tego, co robię.

Mam html:

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

Renderuj funkcję w ten sposób:

...
render: function() {

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

A poniżej nazywam render:

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

Wygenerowany kod HTML wygląda następująco:

<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>

Problem polega na tym, że nie jestem zbyt szczęśliwy, że React zmusza mnie do zawinięcia wszystkiego w div „DeadSimpleComponent”. Jakie jest najlepsze i proste obejście tego problemu bez jawnych manipulacji DOM?

AKTUALIZACJA 28.07.2017: Opiekunowie Reacta dodali tę możliwość w React 16 Beta 1

Od React 16.2 możesz to zrobić:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}
Kirill Reznikov
źródło
4
doskonała praktyka nazewnictwa ;-)
Kirill Reznikov
Czy mogę zobaczyć twój plik HTML? Źle przeczytałem twoje pytanie. Mogę jednak obejść ten problem.
Louis93,
Coś takiego: jsfiddle.net/qawumm3v
Kirill Reznikov
Masz problem z komponentem zawierającym jeden element? Naprawdę?
Dominic
Co masz na myśli? Po prostu próbuję Reacta, nie powinno to być zbyt skomplikowane .. Ale ograniczenie wygląda denerwująco.
Kirill Reznikov

Odpowiedzi:

142

To wymaganie zostało usunięte w wersji React (16.0)] 1 , więc teraz możesz uniknąć tego opakowania.

Możesz użyć React.Fragment, aby wyrenderować listę elementów bez tworzenia węzła nadrzędnego, oficjalny przykład:

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

Więcej tutaj: Fragmenty

Luger
źródło
1
Wspaniała wiadomość DmitryUlyanets. Czy jest planowana data premiery?
Jonas Carlbaum
Jest wydany od 26 września 2017 r., Patrz Reactjs.org/blog/2017/09/26/react-v16.0.html
Tom
56

Aktualizacja 05.12.2017: React 16.2.0 teraz w pełni obsługuje renderowanie fragmentów z ulepszoną obsługą zwracania wielu elementów potomnych z metody renderowania komponentów bez określania kluczy w dzieciach:

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

Jeśli używasz wersji React wcześniejszej niż 16.2.0, możesz również użyć <React.Fragment>...</React.Fragment>zamiast niej:

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

Oryginalny:

React v16.0 wprowadził zwracanie tablicy elementów w metodzie render bez zawijania jej w 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>,
  ];
}

W tej chwili dla każdego elementu wymagany jest klucz, aby uniknąć ostrzeżenia o kluczu, ale można to zmienić w przyszłych wersjach:

W przyszłości prawdopodobnie dodamy specjalną składnię fragmentów do JSX, która nie wymaga kluczy.

Tomek
źródło
Nowa skrócona składnia <> </> jest świetna. Jednak nadal mam co do tego mieszane przeczucia.
Thulani Chivandikwa
@ThulaniChivandikwa Czy mógłbyś wyrazić swoje obawy dotyczące skróconej składni?
Tom
1
Myślę, że bardziej chodzi o koncepcję pustego tagu, która jest dziwna w JSX i niezbyt intuicyjna, chyba że wiesz dokładnie, co robi.
Thulani Chivandikwa
7

Możesz użyć:

render(){
    return (
        <React.Fragment>
           <div>Some data</div>
           <div>Som other data</div>
        </React.Fragment>
    )
}

Więcej informacji można znaleźć w tej dokumentacji .

Rolando Cintron
źródło
3

Użyj [] zamiast (), aby zawinąć cały powrót.

render: function() {
  return[
    <div className="DeadSimpleComponent__time">10:23:12</div >
    <div className="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
  ]
}
Michael Cuneo
źródło
1

Jest to nadal wymagane , ALE React teraz upewnij się, że tworzysz elementy bez tworzenia dodatkowego elementu DOM.

Potrzebne jest dodatkowe opakowanie (zwykle z rodzicem div), ponieważ createElementmetoda Reacts wymaga typeparametru, którym jest either a tag name string (such as 'div' or 'span'), a React component type (a class or a function). Ale to było zanim wprowadzili React Fragment.

Zapoznaj się z tym NOWYM dokumentem API dla createElement

React.createElement : Tworzy i zwraca nowy element React podanego typu. Argument type może być ciągiem znaków z nazwą znacznika (np. „Div” lub „span”), typem komponentu React (klasa lub funkcja) lub typem fragmentu React .

oto oficjalny przykład, Refer React.Fragment .

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}
główny
źródło
0

Nie będziesz w stanie się tego pozbyć div elementu. React.render () musi zwrócić jeden prawidłowy węzeł DOM.

Henrik Andersson
źródło
elementy div są ignorowane, Knockout.JS robi to samo. posiadanie elementu div bez stylizacji zewnętrznej części komponentu nic nie zmienia.
Chris Hawkes,
16
@ChrisHawkes, nie zgadzam się. jeden opakowujący element div wpływa na selektory css.
Downhillski
Podczas pracy z elementami semantycznymi, których nie chcesz być całkowicie komponentami Reacta, staje się to problemem. Powiedzmy, że istnieje tag sekcji z elementami nagłówka i stopki, a między nimi jest kontener mapy Google, którego nie chcemy używać w Reakcie. Wtedy byłoby fajnie mieć nagłówek jako komponent Reacta i stopkę jako komponent Reacta, bez konieczności umieszczania dodatkowych div: s na zewnątrz wewnątrz komponentów Reacta ... To jest po prostu głupi projekt, jeśli w ogóle zależy ci na HTML
drukujesz
0

Oto jeden ze sposobów renderowania „przezroczystych” komponentów:

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>

wprowadź opis obrazu tutaj

Ярослав Рахматуллин
źródło
0

Jest też obejście. Poniższy kod blokowy generuje fragment bez potrzeby 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>
})
erfan seidipoor
źródło
0

Wiem, że odpowiedź na to pytanie została udzielona, ​​możesz oczywiście użyć React.Fragment, który nie tworzy węzła, ale pozwala na grupowanie elementów takich jak div.

Dodatkowo, jeśli chcesz się dobrze bawić, możesz zaimplementować (i nauczyć się wielu rzeczy) tryb React, który usuwa dodatkowe elementy DIV. W tym celu naprawdę chcę udostępnić świetny film o tym, jak możesz to zrobić na samej bazie kodu React.

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

Nie jest to oczywiście coś, co zrobiłbyś w praktyce, ale jest to dobra okazja do nauki.

Gabriel P.
źródło