React v16.2.0: Melhoria no Suporte a Fragmentos

28 de novembro de 2017 por Clement Hoang

O React 16.2 agora está disponível! O maior complemento, é a melhoria ao suporte do retorno a múltiplos filhos de um método de renderização de um componente. Nós chamamos esta funcionaliade de fragmentos:

Fragmentos se parecem com tags JSX vazias. Elas permitem você agrupar uma lista de filhos sem adicionar nós extras ao DOM:

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

Esta empolgante funcionalidade é possível graças a junção do React e do JSX.

O Que São Fragmentos?

Um padrão comum é um componente retornar uma lista de filhos. Observe este exmplo em HTML:

Algum texto.
<h2>Um cabeçalho</h2>
Mais texto.
<h2>Outro cabeçalho</h2>
Ainda mais texto.

Antes da versão 16, a única forma de realizar isto no React, seria encapsulando os filhos em um elemento extra, geralmente uma div ou span:

render() {
  return (
    // Elemento div inconveniente :(
    <div>
      Algum texto.
      <h2>Um cabeçalho</h2>
      Mais texto.
      <h2>Outro cabeçalho</h2>
      Ainda mais texto.
    </div>
  );
}

Para resolver esta limitação, no React 16.0, foi adicionado suporte ao retorno de um array de elementos de um método render de um componente. Ao invés de encapsular os filhos em um elemento DOM, você pode coloca-los dentro de um array:

render() {
 return [
  "Algum texto.",
  <h2 key="heading-1">Um cabeçalho</h2>,
  "Mais texto.",
  <h2 key="heading-2">Outro cabeçalho</h2>,
  "Ainda mais texto."
 ];
}

No entando, isso tem algumas diferenças confusas do JSX normal:

  • Filhos contidos em um array, devem ser separados por víngula.
  • Filhos contidos em um array, devem ter uma chave para prevenir o aviso de chave do React.
  • Strings devem estas entre aspas.

Para providenciar uma maior consistência de exepriência a fragmentos, o React agora fornece um componente Fragment de primeira classe, que pode ser usado em lugar dos arrays.

render() {
  return (
    <Fragment>
      Algum texto.
      <h2>Um cabeçalho</h2>
      Mais texto.
      <h2>Outro cabeçalho</h2>
      Ainda mais texto.
    </Fragment>
  );
}

Você pode usar <Fragment /> da mesma forma que usaria qualquer outro elemento, sem mudar a forma que você escreve JSX. Sem víngulas, sem chaves e sem aspas.

O componente Fragment está disponível no objeto principal React:

const Fragment = React.Fragment;

<Fragment>
  <ChildA />
  <ChildB />
  <ChildC />
</Fragment>

// Isto também funciona
<React.Fragment>
  <ChildA />
  <ChildB />
  <ChildC />
</React.Fragment>

Sintaxe Fragment JSX

Fragments são padrões comuns em nossa base de código no Facebook. Nós antecipamos que eles serão amplamente adotados por outros times. Para tornar a experiência de criação o mais conveniente possível, nós estamos adicionando o suporte sintático aos fragmentos no JSX:

render() {
  return (
    <>
      Algum texto.
      <h2>Um cabeçalho</h2>
      Mais texto.
      <h2>Outro cabeçalho</h2>
      Ainda mais texto.
    </>
  );
}

No React, esta transformação do elemento <React.Fragment/>, como no exemplo da seção anterior. (Frameworks não React que usam JSX talvez compile de forma diferente.)

A sintaxe do Fragmento no JSX foi inspirada pela arte anterior, como o construtor XMLList() <></> no E4X. Usando um par de tags vazias, representa-se a ideia de que não será adicionado um elemento real ao DOM.

Fragmentos com Chave

Observe que a sintaxe <></> não aceita atributos, incluindo chaves (key).

Se você precisa de um fragmento com chave, você pode usar o <Fragment /> diretamente. Um caso de uso seria mapear uma coleção para um array de fragmentos — por exemplo, para criar uma lista de descrição:

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Sem a `key`, o React irá exibir um alerta sobre a key
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

key é o único atributo qual pode ser passado ao Fragment. No futuro, nós provavelmente adicionaremos suporte aos de mais atributos, tais como os manipuladores de eventos.

Demonstração Ao Vivo

Você pode experimentar a sintaxe fragment JSX com este CodePen.

Suporte à Sintaxe Fragment

O suporte à sintaxe de fragmento no JSX irá variar dependendo das ferramentas quais você utiliza para construir o seu app. Por favor, seja paciente enquanto a comunidade JSX trabalha para adotar a nova sintaxe. Nós temos trabalhado próximo dos responsáveis dos projetos mais populares:

Create React App

O suporte experimental à sintaxe de fragment será adicionado ao Create React App dentro de poucos dias. Uma versão estável talvez leve mais tempo, enquanto esperamos a adoção por projetos principiantes.

Babel

O suporte ao fragmento JSX encontra-se disponível no Babel v7.0.0-beta.31 e versões superiores! Se você já utiliza o Babel 7, apenas atualize para a última versão do Babel e do plugin transform:

# para usuários que utilizam yarn
yarn upgrade @babel/core @babel/plugin-transform-react-jsx
# para usuários que utilizam npm
npm update @babel/core @babel/plugin-transform-react-jsx

Ou se você está usando o react preset:

# para usuários que utilizam yarn
yarn upgrade @babel/core @babel/preset-react
# para usuários que utilizam npm
npm update @babel/core @babel/preset-react

Observe que o Babel 7 ainda se encontra na versão beta, a versão estável chegará em breve.

Infelizmente o suporte ao Babel 6.x não está disponível, e não há atualmente planos para faze-lo retrocompatível.

Babel com Webpack (babel-loader)

Se você está utilizando o Babel com Webpack, não é necessário nenhuma etapa adicional, porque o babel-loader utilizará sua versão internamente já instalada do Babel.

Babel com Outros Frameworks

Se você utiliza JSX com um framework não baseado em React, como Inferno ou Preact, há uma opção de diretiva no babel-plugin-transform-react-jsx, que configura o compilador do Babel para alterar a sintaxe <></> para um identificador personalizado.

TypeScript

O TypeScript possui total suporte à sintaxe de fragmento! Por favor, atualize para a versão 2.6.2. (Note que é imporante mesmo se você já está na versão 2.6.1, sendo que o suporte foi adicionado como atualização de complemento na versão 2.6.2.)

Atualize para a última versão do TypeScript utilizando este comando:

# para usuários que utilizam yarn
yarn upgrade typescript
# para usuários que utilizam npm
npm update typescript

Flow

O suporte do Flow aos fragmentos JSX estão disponíveis a partir da versão 0.59! Apenas execute

# para usuários que utilizam yarn
yarn upgrade flow-bin
# para usuários que utilizam npm
npm update flow-bin

para atualizar o Flow para a última versão.

Prettier

O Prettier adicionou suporte à fragmentos em sua versão 1.9.

ESLint

Fragmentos JSX são suportados pelo ESLint 3.x, quando este é utilizado junto ao babel-eslint:

# para usuários que utilizam yarn
yarn add eslint@3.x babel-eslint@7
# para usuários que utilizam npm
npm install eslint@3.x babel-eslint@7

ou se você já utiliza, então atualize:

# para usuários que utilizam yarn
yarn upgrade eslint@3.x babel-eslint@7
# para usuários que utilizam npm
npm update eslint@3.x babel-eslint@7

Assegure que você tenha a seguinte linha dentro de seu .eslintrc:

"parser": "babel-eslint"

É isso aí!

Observe que o babel-eslint não é oficialmente suportado pelo ESLint. Nós estaremos procurando adicionar o suporte aos fragmentos ao ESLint 4.x ao decorrer das próximas semanas (veja a discussão #9662)

Suporte do Editor

Talvez demore um pouco para a sintaxe do fragmento ser suportada pelo seu editor de texto. Por favor, seja paciente enquanto a comunidade trabalha para adotar as últimas mudanças. Ao decorrer deste meio tempo, você talvez veja erros ou inconsistências de destacamento se o seu editor ainda não suporta a sintaxe de fragmento. Geralmente, estes erros podem ser desconsiderados com segurança.

Suporte ao Editor de TypeScript

Se você é um usuário de TypeScript — boas notícias! O suporte do editor à sintaxe de fragmentos JSX já encontra-se disponível em Visual Studio 2015, Visual Studio 2017, Visual Studio Code e Sublime Text via Gerenciador de Pacote.

Outras Ferramentas

Para outras ferramentas, por favor, verifique com a documentação correspondente se há suporte disponível. Porém, se você estiver restrito pelo seu ferramental, você pode sempre começar usando o componente <Fragment> e realizar uma refatoração depois, para assim, utilizar da sintaxe abreviada quando o suporte apropriado estiver disponível.

Instalação

O React v16.2.0 está disponível no registro npm.

Para instalar o React 16 com o Yarn, execute:

yarn add react@^16.2.0 react-dom@^16.2.0

Para instalar o React 16 com o npm, execute:

npm install --save react@^16.2.0 react-dom@^16.2.0

Nós também fornecemos compilações UMD do React via CDN:

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

Consulte a documentação para instruções de instalações detalhadas.

Histórico de Mudanças

React

  • Adiciona o Fragment como uma exportação nomeada ao React. (@clemmy em #10783)
  • Suporte experimental aos tipos de Chamada/Retorno nos utilitários React.Children. (@MatteoVH em #11422)

React DOM

  • Correção da seleção dos botões de rádio, quando utilizado múltiplas listas de rádios. (@landvibe em #11227)
  • Correção dos botões de rádio, referente ao não recebimento do evento onChange em alguns casos. (@jquense em #11028)

Renderizador de Teste React

  • Correção da chamada ao callback setState(), quanto ao acionamento antecipado através do componentWillMount. (@accordeiro em #11507)

React Reconciler

  • Expõe o react-reconciler/reflection junto aos utilitários para os renderizadores personalizados. (@rivenhk em #11683)

Mudanças Internas

Agradecimentos

Esta versão se tornou possível graças aos nossos colaboradores de código aberto. Um grande obrigado a todos aqueles que relataram problemas, contribuiram com discussões sobre a sintaxe, revisaram as solicitações de mudanças, adicionaram suporte aos fragmentos JSX em bibliotecas terceiras, e mais!

Um agradecimento especial aos times do TypeScript e Flow, assim como, aos responsáveis do Babel, quem nos ajudou a produzir o ferramental de suporte para a nova sintaxe funcionar perfeitamente.

Obrigado ao Gajus Kuizinas e aos outros contribuidores que prototiparam o componente Fragment em código aberto.