Como evitar empacotamento extra <div> no React?

114

Hoje comecei a aprender ReactJS e depois de uma hora enfrentei o problema .. Quero inserir um componente que tem duas linhas dentro de uma div na página. Um exemplo simplificado do que estou fazendo abaixo.

Eu tenho um html:

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

Renderizar a função como esta:

...
render: function() {

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

E abaixo estou chamando render:

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

O HTML gerado tem a seguinte aparência:

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

O problema que não estou muito feliz é que o React me forçou a embrulhar tudo em um div "DeadSimpleComponent". Qual é a melhor e mais simples solução alternativa para isso, sem manipulações explícitas de DOM?

ATUALIZAÇÃO 28/07/2017: Mantenedores do React adicionaram essa possibilidade no React 16 Beta 1

Desde React 16.2 , você pode fazer isso:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}
Kirill Reznikov
fonte
4
prática perfeita de nomenclatura ;-)
Kirill Reznikov
Posso ver seu arquivo HTML? Eu li mal sua pergunta. Posso ter uma solução alternativa.
Louis93
Smth assim: jsfiddle.net/qawumm3v
Kirill Reznikov
Você tem um problema com um componente que tem um único elemento? Realmente?
Dominic
O que você quer dizer? Estou apenas tentando React, não deve ser muito complicado .. Mas a limitação parece irritante.
Kirill Reznikov

Respostas:

142

Este requisito foi removido na versão React (16.0)] 1 , então agora você pode evitar esse invólucro.

Você pode usar React.Fragment para renderizar uma lista de elementos sem criar um nó pai, exemplo oficial:

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

Mais aqui: Fragmentos

Luger
fonte
1
Boas notícias, DmitryUlyanets. Existe alguma data de lançamento planejada?
Jonas Carlbaum de
Foi lançado desde 26 de setembro de 2017, consulte reactjs.org/blog/2017/09/26/react-v16.0.html
Tom
56

Atualização 05-12-2017: React v16.2.0 agora oferece suporte total à renderização de fragmentos com suporte aprimorado para retornar vários filhos de um método de renderização de componentes sem especificar chaves nos filhos:

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

Se você estiver usando uma versão do React anterior à v16.2.0, também é possível usar <React.Fragment>...</React.Fragment>:

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

Original:

O React v16.0 apresentou o retorno de uma matriz de elementos no método de renderização sem envolvê-lo em um 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>,
  ];
}

No momento, uma chave é necessária para cada elemento para evitar o aviso de chave, mas isso pode ser alterado em versões futuras:

No futuro, provavelmente adicionaremos uma sintaxe de fragmento especial ao JSX que não requer chaves.

Tom
fonte
A nova sintaxe abreviada de <> </> é excelente. Ainda tenho muitos sentimentos confusos sobre isso.
Thulani Chivandikwa
@ThulaniChivandikwa Você se importaria de expressar suas dúvidas sobre a sintaxe abreviada?
Tom
1
Eu acho que é mais sobre o conceito de uma tag vazia ser estranha no JSX e não muito intuitiva, a menos que você saiba exatamente o que ela faz.
Thulani Chivandikwa
7

Você pode usar:

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

Para obter mais detalhes, consulte esta documentação .

Rolando Cintron
fonte
3

Use [], em vez de () para envolver todo o retorno.

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

Isso ainda é necessário , MAS React agora certifique-se de criar elementos sem criar um elemento DOM adicional.

O empacotamento extra necessário (normalmente com um pai div) porque o createElementmétodo Reacts requer um typeparâmetro que é either a tag name string (such as 'div' or 'span'), a React component type (a class or a function). Mas isso foi antes de eles apresentarem o ReactFragment .

Consulte este NOVO api doc para createElement

React.createElement : cria e retorna um novo elemento React do tipo fornecido. O argumento de tipo pode ser uma string de nome de tag (como 'div' ou 'span'), um tipo de componente React (uma classe ou função) ou um tipo de fragmento React .

aqui está o exemplo oficial, Refer React.Fragment .

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

Você não conseguirá se livrar desse divelemento. React.render () precisa retornar um nó DOM válido.

Henrik Andersson
fonte
os divs são ignorados, Knockout.JS faz a mesma coisa. ter um div sem estilo na parte externa do componente não afeta nada.
Chris Hawkes
16
@ChrisHawkes, discordo. um wrapper div afeta os seletores css.
Downhillski
Ao trabalhar com elementos semânticos, que você não deseja que sejam inteiramente componentes do React, isso se torna um problema. Digamos que haja uma tag de seção com elementos de cabeçalho e rodapé e, entre eles, um contêiner de mapa do google, que não queremos usar no React. Então seria bom ter header como um componente React e Footer como um componente React, sem ter que incluir div: s extras fora para dentro dos componentes React ... Esse é um design estúpido, se você se preocupa com o html sua saída ...
Jonas Carlbaum
0

Esta é uma maneira de renderizar componentes "transculentes":

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>

insira a descrição da imagem aqui

Ярослав Рахматуллин
fonte
0

Também há uma solução alternativa. O código de bloco abaixo gera fragmentos sem a necessidade de 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
fonte
0

Sei que essa pergunta foi respondida, você pode usar React.Fragment, que não cria um nó, mas permite agrupar coisas como um div.

Além disso, se você quiser se divertir, pode implementar (e aprender muitas coisas) um modo React que remove os divs extras e para isso eu realmente quero compartilhar um ótimo vídeo sobre como você pode fazer isso na própria base do código react.

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

Obviamente, isso não é algo que você faria na prática, mas é uma boa oportunidade de aprendizado.

Gabriel P.
fonte