Introducción a la nueva transformación de JSX
Aunque React 17 no tiene nuevas funcionalidades, brindará soporte para la nueva transformación de JSX. En este post, describiremos qué es y cómo probarla.
¿Qué es una transformación de JSX?
Los navegadores no entienden JSX por defecto, por lo que la mayoría de usuarios de React utilizan un compilador como Babel o TypeScript para transformar el código JSX en JavaScript normal. Muchos kit de herramientas preconfigurados como Create React App o Next.js también incluyen una transformación de JSX internamente.
Junto con el lanzamiento de React 17, queríamos hacer algunas mejoras en la transformación de JSX, pero no queríamos romper las configuraciones existentes. Es por eso que trabajamos con Babel para ofrecer una nueva versión reescrita de la transformación de JSX para las personas que quisieran actualizar.
La actualización a la nueva transformación es opcional, pero tiene algunos beneficios:
- Con la nueva transformación, puedes usar JSX sin importar React.
- Dependiendo de tu configuración, tu salida compilada puede mejorar ligeramente el tamaño del paquete.
- Permitirá futuras mejoras que reducen la cantidad de conceptos que necesitas para aprender React.
Esta actualización no cambiará la sintaxis de JSX y no es obligatoria. La antigua transformación de JSX seguirá funcionando como de costumbre y no hay planes para quitarle el soporte.
React 17 RC ya permite utilizar la nueva transformación, ¡así que pruébalo! Para que sea más fácil de adoptar, también lo hemos extendido a React 16.14.0, React 15.7.0, y React 0.14.10. Puedes encontrar las instrucciones de actualización para diferentes herramientas a continuación.
Ahora echemos un vistazo más de cerca a las diferencias entre la transformación antigua y la nueva.
¿Qué es diferente en la nueva transformación?
Cuando usas JSX, el compilador lo transforma en llamadas a funciones de React que el navegador pueda entender. La antigua transformación de JSX convirtió JSX en llamadas a React.createElement(...)
.
Por ejemplo, digamos que tu código fuente se ve así:
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
Internamente, la antigua transformación de JSX lo convierte en JavaScript normal:
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
Nota
Tu código fuente no necesita cambiar de ninguna manera. Estamos describiendo cómo la tranformación de JSX convierte tu código fuente JSX en código JavaScript que un navegador puede entender.
Sin embargo, esto no es perfecto:
- Debido a que JSX se compiló en
React.createElement
,React
debe estar dentro del alcance si usas JSX. - Hay algunas mejoras de rendimiento y simplicaciones que
React.createElement
no permiten.
Para resolver estos problemas, React 17 introduce dos nuevos puntos de entrada al paquete React que están destinados a ser utilizados solo por compiladores como Babel y TypeScript. En lugar de transformar JSX en React.createElement
, la nueva transformación de JSX importa automáticamente funciones especiales de esos nuevos puntos de entrada en el paquete de React y las llama.
Digamos que tu código fuente se ve así:
function App() {
return <h1>Hello World</h1>;
}
Esto es lo que compila la nueva transformación de JSX:
// Insertado por un compilador (¡no lo importes tú mismo!)
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
¡Ten en cuenta que nuestro código original ya no necesita importar React para usar JSX! (Pero aún necesitaríamos importar React para poder usar Hooks u otras exportaciones que proporciona React).
Este cambio es totalmente compatible con todo el código JSX existente, por lo que no tendrás que cambiar tus componentes. Si tienes curiosidad, puedes consultar el RFC técnico para obtener más detalles sobre cómo funciona la nueva transformación.
Nota
Las funciones dentro de
react/jsx-runtime
yreact/jsx-dev-runtime
solo deben ser usadas por la transformación del compilador. Si necesitas crear elementos manualmente en tu código, debes seguir usandoReact.createElement
. Seguirá funcionando y no desaparecerá.
Cómo actualizar a la nueva transformación de JSX
Si no estás listo para actualizar a la nueva transformación de JSX o si estás utilizando JSX para otra biblioteca, no te preocupes. La transformación anterior no se eliminará y seguirá siendo compatible.
Si deseas actualizar, necesitarás dos cosas:
- Una versión de React que admita la nueva transformación (React 17 RC y superior lo admite, pero también hemos publicado React 16.14.0, React 15.7.0, and React 0.14.10 para las personas que aún utilizan versiones mayores anteriores).
- Un compilador compatible (consulta las instrucciones para las diferentes herramientas a continuación).
Dado que la nueva transformación de JSX no requiere que React esté dentro del alcance, también hemos preparado un script automatizado que eliminará las importaciones innecesarias de tu código base.
Create React App
Create React App 4.0.0+ usa la nueva transformación para versiones compatibles de React.
Next.js
Next.js v9.5.3+ usa la nueva transformación para versiones compatibles de React.
Gatsby
Gatsby v2.24.5+ usa la nueva transformación para versiones compatibles de React.
Nota
Si recibes este error de Gatsby después de actualizar a React 17 RC, ejecuta
npm update
para solucionarlo.
Configuración manual de Babel
El soporte para la nueva transformación de JSX está disponible en Babel v7.9.0 y superior.
Primero, deberás actualizar a la última versión de Babel y del plugin de la transformación.
Si estás usando @babel/plugin-transform-react-jsx
:
# for npm users
npm update @babel/core @babel/plugin-transform-react-jsx
# for yarn users
yarn upgrade @babel/core @babel/plugin-transform-react-jsx
Si estás usando @babel/preset-react
:
# for npm users
npm update @babel/core @babel/preset-react
# for yarn users
yarn upgrade @babel/core @babel/preset-react
Actualmente, la antigua transformación {"runtime": "classic"}
es la opción predeterminada. Para habilitar la nueva transformación, puedes pasar {"runtime": "automatic"}
como una opción a @babel/plugin-transform-react-jsx
o @babel/preset-react
:
// If you are using @babel/preset-react
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
// If you're using @babel/plugin-transform-react-jsx
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
A partir de Babel 8, "automatic"
será el tiempo de ejecución para ambos complementos. Para obtener más información, consulta la documentación de Babel para @babel/plugin-transform-react-jsx y @babel/preset-react.
Nota
Si usas JSX con una biblioteca que no sea React, puedes usar la opción
importSource
para importar desde esa biblioteca — siempre que proporcione los puntos de entrada necesarios. Alternativamente, puedes seguir usando la transformación clásica que seguirá siendo compatible.Si eres autor de una biblioteca y estás implementando el punto de entrad
/jsx-runtime
para ella, ten en cuenta que hay un caso en el que incluso la nueva transformación tiene que recurrir acreateElement
por motivos de retrocompatibilidad. En este caso, autoimportarácreateElement
directamente del punto de entrada raíz especificado porimportSource
.
ESLint
Si estás utilizando eslint-plugin-react, las reglas react/jsx-uses-react
y react/react-in-jsx-scope
ya no son necesarias y se pueden desactivar o eliminar.
{
// ...
"rules": {
// ...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
TypeScript
TypeScript admite la transformación de JSX en v4.1 y superior.
Flow
Flow admite la transformación de JSX en v0.126.0 y posteriores al añadir react.runtime-automatic
a tus opciones de configuración de Flow.
Eliminación de importaciones React no utilizadas
Debido a que la nueva transformación de JSX importará automáticamente las funciones react/jsx-runtime
necesarias, React no necesitará estar dentro del alcance cuando use JSX. Esto podría dar lugar a importaciones de React no utilizadas en tu código. No está de más conservarlas, pero si deseas eliminarlas, te recomendamos que ejecutes un script “codemod” para eliminarlas automáticamente:
cd your_project
npx react-codemod update-react-imports
Nota
Si recibes errores al ejecutar el codemod, intenta especificar un dialecto de JavaScript diferente cuando
npx react-codemod update-react-imports
te pida que elijas uno. En particular, en este momento, la configuración “JavaScript con Flow” admite una sintaxis más nueva que la configuración de “JavaScript”, incluso si no usas Flow. Crea un issue si tienes problemas.Ten en cuenta que la salida de codificación no siempre coincidirá con el estilo de codificación de tu proyecto, por lo que es posible que desees ejecutar Prettier después de que finalice la codificación para lograr un formateo coherente.
Ejecutar este codemod:
- Eliminará todas las importaciones de React no utilizadas como resultado de la actualización a la nueva transformación JSX.
- Cambiará todas las importaciones de React predeterminadas (es decir
import React from "react"
) a importaciones con nombre desestructuradas (ej.import { useState } from "react"
), que será el estilo preferido en el futuro. Este codemod no afectará las importaciones de espacios de nombre existentes (es decirimport * as React from "react"
) que también es un estilo válido. Las importaciones predeterminadas seguirán funcionando en React 17, pero a largo plazo recomendamos alejarse de ellas.
Por ejemplo,
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
será reemplazado con
function App() {
return <h1>Hello World</h1>;
}
Si usas alguna otra importación de React, por ejemplo, un Hook, entonces el codificador lo convertirá en una importación con nombre.
por ejemplo,
import React from 'react';
function App() {
const [text, setText] = React.useState('Hello World');
return <h1>{text}</h1>;
}
será reemplazado con
import { useState } from 'react';
function App() {
const [text, setText] = useState('Hello World');
return <h1>{text}</h1>;
}
Además de limpiar las importaciones no utilizadas, esto también te ayudará a prepararse para una futura versión principal de React (no React 17) que admitirá los módulos ES y no tendrás una exportación predeterminada.
Gracias
Nos gustaría agradecer a los mantenedores de Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint y Flow por su ayuda para implementar e integrar la nueva transformación de JSX. También queremos agradecer a la comunidad React por sus comentarios y discusiones sobre el RFC técnico relacionado.