Apresentando o novo JSX Transform
Embora o React 17 não contenha novos recursos, ele fornecerá suporte para uma nova versão do JSX Transform. Neste post, descreveremos o que é e como experimentá-lo.
O Que é um JSX Transform?
Os navegadores não entendem JSX imediatamente, então a maioria dos usuários do React confia em um compilador como o Babel ou TypeScript para transformar o código JSX em JavaScript regular. Muitos toolkits pré-configurados como o Create React App ou Next.js também incluem um JSX Transform por baixo do capô.
Junto com a versão React 17, queríamos fazer algumas melhorias no JSX Transform, mas não queríamos quebrar as configurações existentes. É por isso que trabalhamos com Babel para oferecer uma versão nova e reescrita do JSX Transform para pessoas que gostariam de atualizar.
Atualizar para a nova transformação é totalmente opcional, mas tem alguns benefícios:
- Com a nova transformação, você pode usar JSX sem importar o React.
- Dependendo de sua configuração, a saída compilada pode melhorar ligeiramente o tamanho do pacote.
- Isso permitirá melhorias futuras que reduzem o número de conceitos que você precisa para aprender React.
Esta atualização não mudará a sintaxe JSX e não é necessária. O antigo JSX Transform continuará funcionando normalmente e não há planos de remover o suporte para ele.
React 17 RC já inclui suporte para a nova transformação, então experimente! Para facilitar a adoção também adaptamos seu suporte para React 16.14.0, React 15.7.0 e React 0.14.10. Você pode encontrar as instruções de atualização para diferentes ferramentas abaixo.
Agora, vamos examinar mais de perto as diferenças entre a velha e a nova transformação.
O Que Há de Diferente na Nova Transformação?
Quando você usa JSX, o compilador o transforma em chamadas de função React que o navegador pode entender. A antiga transformação JSX transforma JSX em chamadas React.createElement(...)
.
Por exemplo, digamos que seu código-fonte tenha a seguinte aparência:
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
Nos bastidores, a antiga transformação JSX o transforma em JavaScript regular:
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
Nota
Seu código-font não precisa ser alterado de forma alguma. Estamos descrevendo como a transformação JSX transforma seu código-fonte JSX no código JavaScript que um navegador pode entender.
No entanto, isso não é perfeito:
- Como JSX foi compilado em
React.createElement
,React
precisa estar no escopo se você usasse JSX. - Existe algumas melhorias e simplificações de desempenho que
React.createElement
não permite.
Para resolver esses problemas, o React 17 apresenta dois novos pontos de entrada para o pacote React que devem ser usados apenas por compiladores como Babel e TypeScript. Em vez de transformar JSX em React.createElement
, a nova transformação JSX importa automaticamente funções especiais desses novos pontos de entrada no pacote React e os chama.
Digamos que seu código-fonte tenha a seguinte aparência:
function App() {
return <h1>Hello World</h1>;
}
É para isso que a nova transformação JSX o compila:
// Inserido por um compilador (não importe você mesmo!)
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
Observe como nosso código original não precisava mais importar o React para usar JSX! (Mas ainda precisaríamos importar o React para usar Hooks ou outras exportações que o React fornece.)
Esta mudança é totalmente compatível com todo o código JSX existente, assim você não terá que mudar seus componentes. Se estiver curioso, você pode verificar a RFC técnica para obter mais detalhes sobre como a nova transformação funciona.
Nota
As funções dentro de
react/jsx-runtime
ereact/jsx-dev-runtime
devem ser usadas apenas pela transformação do compilador. Se você precisa criar elementos manualmente em seu código, você deve continuar usandoReact.createElement
. Ele continuará a funcionar e não irá embora.
Como Fazer Upgrade para a Nova Transformação JSX
Se você não estiver pronto para atualizar para a nova transformação JSX ou se estiver usando JSX para outra biblioteca, não se preocupe. A transformação antiga não será removida e continuará a ter suporte.
Se quiser fazer upgrade, você precisará de duas coisas:
- Uma versão do React que suporta a nova transformação (React 17 RC e superior suportam, mas também lançamos React 16.14.0, React 15.7.0 e React 0.14.10 para pessoas que ainda estão nas versões principais mais antigas).
- Um compilador compatível (consulte as instruções para diferentes ferramentas abaixo).
Como a nova transformação JSX não exige que o React esteja no escopo, também preparamos um script automatizado que removerá as importações desnecessárias de sua base de código.
Create React App
Create React App 4.0.0+ usa a nova transformação para versões compatíveis do React.
Next.js
Next.js v9.5.3+ usa a nova transformação para versões compatíveis do React.
Gatsby
Gatsby v2.24.5+ usa a nova transformação para versões compatíveis do React.
Nota
Se você obtiver este erro de Gatsby após atualizar para React 17 RC, execute
npm update
para corrigi-lo.
Configuração Manual do Babel
O suporte para a nova transformação JSX está disponível no Babel v7.9.0 e superior.
Primeiro, você precisará atualizar para a última transformação do Babel e do plugin.
Se você estiver usando @babel/plugin-transform-react-jsx
:
# para usuários npm
npm update @babel/core @babel/plugin-transform-react-jsx
# para usuários yarn
yarn upgrade @babel/core @babel/plugin-transform-react-jsx
Se você estiver usando @babel/preset-react
:
# para usuários npm
npm update @babel/core @babel/preset-react
# para usuários yarn
yarn upgrade @babel/core @babel/preset-react
Atualmente, a antiga transformação {"runtime": "classic"}
é a opção padrão. Para habilitar a nova transformação, você pode passar {"runtime": "automatic"}
como uma opção para @babel/plugin-transform-react-jsx
ou @babel/preset-react
:
// Se você estiver usando @babel/preset-react
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
// Se você estiver usando @babel/plugin-transform-react-jsx
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
A partir do Babel 8, "automatic"
será o tempo de execução padrão para ambos os plug-ins. Para obter mais informações, verifique a documentação do Babel para @babel/plugin-transform-react-jsx e @babel/preset-react.
Nota
Se você usar JSX com uma biblioteca diferente de React, você pode usar a opção
importSource
para importar dessa biblioteca - desde que forneça os pontos de entrada necessários. Como alternativa, você pode continuar usando a transformação clássica, que continuará a ser compatível.Se você é um autor de biblioteca e está implementando o ponto de entrada
/jsx-runtime
para sua biblioteca, tenha em mente que há um caso em que até mesmo a nova transformação tem que voltar paracreateElement
para compatibilidade de versões anteriores. Nesse caso, ele irá importar automaticamentecreateElement
diretamente do ponto de entrada root especificado porimportSource
.
ESLint
Se você estiver usando eslint-plugin-react, as regras de react/jsx-uses-react
e react/react-in-jsx-scope
não são mais necessárias e podem ser desativadas ou removidas.
{
// ...
"rules": {
// ...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
TypeScript
TypeScript suporta a nova transformação JSX em v4.1.
Flow
Flow suporta a nova transformação JSX em v0.126.0 para cima, adicionando react.runtime = automatic
às opções de configuração do Flow.
Removendo Imports React não Utilizadas
Como a nova transformação JSX importará automaticamente as funções react/jsx-runtime
necessárias, o React não precisará mais estar no escopo quando você usar JSX. Isso pode levar a importação React não utilizadas em seu código. Não faz mal mantê-los, mas se quiser removê-los, recomendamos a execução de um script “codemod” para removê-los automaticamente:
cd your_project
npx react-codemod update-react-imports
Nota
Se você estiver recebendo errors ao executar o codemod, tente especificar um dialeto JavaScript diferente quando
npx react-codemod update-react-imports
solicitar que você escolha um. Em particular, neste momento, a configuração “JavaScript com Flow” suporta sintaxe mais recente do que a configuração “JavaScript”, mesmo se você não usar o Flow. Crie uma issue se você tiver problemas.Lembre-se de que a saída do codemod nem sempre corresponderá ao estilo de codificação do seu projeto, então você pode querer executar Prettier depois que o codemod terminar para uma formatação consistente.
Executar este codemod irá:
- Remover todas as importações React não utilizadas como resultado da atualização para a nova transformação JSX.
- Alterar todas as importações React padrão (ou seja,
import React from "react"
) para importações nomeadas desestruturadas (ex.import { useState } from "react"
), que é o estilo preferido no futuro. Este codemod não afetará as importações de namespace existentes (ou seja,import * as React from "react"
), que também é um estilo válido. As importações padrão continuarão funcionando no React 17, mas, a longo prazo, encorajamos nos afastar delas.
Por exemplo,
import React from 'react';
function App() {
return <h1>Olá Mundo</h1>;
}
será substituído por
function App() {
return <h1>Olá Mundo</h1>;
}
Se você usar alguma outra importação do React - por exemplo, um Hook - então o codemod irá convertê-lo em uma importação nomeada.
Por exemplo,
import React from 'react';
function App() {
const [text, setText] = React.useState('Olá Mundo');
return <h1>{text}</h1>;
}
será substituído por
import { useState } from 'react';
function App() {
const [text, setText] = useState('Olá Mundo');
return <h1>{text}</h1>;
}
Além de limpar as importações não utilizadas, isso também o ajudará a se preparar para uma versão principal futura do React (não do React 17), que oferecerá suporte aos Módulos ES e não terá uma exportação padrão.
Obrigado
Gostaríamos de agradecer aos mantenedores de Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint e Flow por sua ajuda na implementação e integração da nova transformação JSX. Também queremos agradecer à comunidade React por seus comentários e discussões sobre a RFC técnica.