We want to hear from you!Take our 2020 Community Survey!

Introducción a la nueva transformación de JSX

September 22, 2020 by Luna Ruan

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:

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 y react/jsx-dev-runtime solo deben ser usadas por la transformación del compilador. Si necesitas crear elementos manualmente en tu código, debes seguir usando React.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 a createElement por motivos de retrocompatibilidad. En este caso, autoimportará createElement directamente del punto de entrada raíz especificado por importSource.

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 decir import * 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.

¿Es útil esta página?Edita esta página