Como desarrolladores de WordPress, a menudo integramos componentes React personalizados en nuestros temas y plugins para crear interfaces de usuario dinámicas y con capacidad de respuesta.

Con el próximo lanzamiento de React 19, es crucial prepararse para los cambios y deprecaciones que podrían afectar a nuestras bases de código existentes. WordPress 6.6, que se lanzará el 16 de julio, incluye React 18.3. Esta versión es casi idéntica a la 18.2, pero añade advertencias sobre funciones obsoletas para ayudarte a prepararte para React 19.

Abordar estas deprecaciones es esencial para garantizar la compatibilidad con React 19, e ignorarlas puede provocar errores o problemas en tus bloques personalizados, plugins o temas cuando React 19 se publique y se incluya en WordPress.

Este artículo detalla cada deprecación, proporciona ejemplos de código y te guía a través del proceso de reemplazar las funcionalidades deprecadas para mantener un funcionamiento fluido.

Deprecaciones eliminadas en React

Se han eliminado varias APIs y funciones obsoletas para racionalizar la biblioteca React y fomentar las mejores prácticas. Esta sección explica los cambios más importantes y cómo actualizar tu código en consecuencia.

1. Eliminación de defaultProps para componentes de función

React 19 eliminará defaultProps para los componentes de función en favor de los parámetros por defecto de ES6. Según el equipo de WordPress, esta deprecación es más común en plugins y temas.

Como desarrollador de WordPress, es posible que utilices defaultProps para proporcionar valores por defecto a los props en tus componentes de función, asegurándote de que los componentes se comportan correctamente incluso si no se pasan ciertos props.

Este es el aspecto que podría tener tu código actual con defaultProps:

function CustomButton({ label, color }) {
    return <button style={{ backgroundColor: color }}>{ label }</button>;
}

CustomButton.defaultProps = {
    label: 'Click me',
    color: 'blue',
};

En este ejemplo, un componente CustomButton tiene valores por defecto label y color proporcionados por defaultProps. Con React 19, esto lanzará un error de advertencia, instándote a utilizar en su lugar los parámetros por defecto de ES6.

Aquí tienes el código actualizado con los parámetros por defecto de ES6:

function CustomButton({ label = 'Click me', color = 'blue' }) {
    return <button style={{ backgroundColor: color }}>{ label }</button>;
}

Usando parámetros por defecto ES6, los valores por defecto están ahora directamente en la firma de la función, haciendo el código más fácil de leer y mantener.

2. Eliminación de propTypes para componentes de función

propTypes fue deprecado en React 15.5.0 y será completamente eliminado del paquete React en la versión 19. Si estás utilizando propTypes, se recomienda migrar a TypeScript o a otra solución de verificación de tipos.

Puede que hayas estado utilizando propTypes para validar los props pasados a tus componentes de función para asegurarte de que reciben los tipos y valores correctos. Por ejemplo:

import PropTypes from 'prop-types';

function CustomButton({ label, color }) {
    return <button style={{ backgroundColor: color }}>{ label }</button>;
}

CustomButton.defaultProps = {
    label: 'Click me',
    color: 'blue',
};

CustomButton.propTypes = {
    label: PropTypes.string,
    color: PropTypes.string,
};

Hoy puedes empezar a utilizar TypeScript para estas verificaciones de tipos:

type CustomButtonProps = {
    label?: string;
    color?: string;
};

const CustomButton = ({ label = 'Click me', color = 'blue' }: CustomButtonProps) => {
    return <button style={{ backgroundColor: color }}>{ label }</button>;
};

3. Eliminación de Legacy Context (contextTypes y getChildContext)

Dada la antigüedad de muchos plugins y bases de código de WordPress, es posible que aún utilices las APIs heredadas contextTypes y getChildContext en tus componentes de clase. Estas APIs se utilizaban para pasar datos de un componente padre a sus descendientes sin pasar explícitamente props en cada nivel.

Sin embargo, es importante tener en cuenta que el contexto heredado fue deprecado en React 16.6.0 y se eliminará en React v19. Con este cambio se pretende que React sea algo más pequeño y rápido, ya que la API Legacy Context tenía fallos sutiles que a menudo eran fáciles de pasar por alto.

El método legacy ha sido sustituido por la nueva API contextType.

Aquí tienes un ejemplo de cómo puedes estar utilizando la API Context deprecada en un plugin de WordPress para pasar ajustes globales, como el título del sitio, desde un componente padre a un componente hijo sin prop drilling:

import PropTypes from 'prop-types';

class SettingsProvider extends React.Component {
  static childContextTypes = {
    siteTitle: PropTypes.string.isRequired,
  };

  getChildContext() {
    return { siteTitle: 'My WordPress Site' };
  }

  render() {
    return <SettingsConsumer />;
  }
}

class SettingsConsumer extends React.Component {
  static contextTypes = {
    siteTitle: PropTypes.string.isRequired,
  };

  render() {
    return <div>Site Title: {this.context.siteTitle}</div>;
  }
}

En cambio, el enfoque moderno utiliza el método createContext. Este es el método que debes adoptar mientras te preparas para React 19:

import React from 'react';

const SettingsContext = React.createContext();

class SettingsProvider extends React.Component {
  render() {
    return (
      <SettingsContext value={{ siteTitle: 'My WordPress Site' }}>
        <SettingsConsumer />
      </SettingsContext>
    );
  }
}

class SettingsConsumer extends React.Component {
  static contextType = SettingsContext;

  render() {
    const { siteTitle } = this.context;
    return <div>Site Title: { siteTitle }</div>;
  }
}

4. Eliminación de las referencias de cadena (string refs)

El uso de referencias de cadena (string refs) fue una forma común de acceder a un elemento del DOM en componentes React. Sin embargo, han sido consideradas obsoletas desde React 16.3.0 y serán eliminadas en la v19.

Aunque las referencias de cadena eran sencillas, tenían varios problemas, como posibles conflictos de nombres y falta de flexibilidad.

Considera un ejemplo de uso de referencias de cadena en un bloque personalizado de WordPress. Imagina que tienes un bloque personalizado de Gutenberg que incluye un campo de entrada, y quieres que el campo de entrada se enfoque automáticamente cuando el bloque se añada al editor. Así es como podrías haberlo hecho utilizando referencias de cadena:

class CustomBlock extends React.Component {
  componentDidMount() {
    this.refs.input.focus();
  }

  render() {
    return <input ref="input" placeholder="Enter text..." />;
  }
}

Para prepararte para React 19, debes sustituir las string refs con callback refs o la API React.createRef. Aquí tienes el mismo ejemplo utilizando una callback ref:

class CustomBlock extends React.Component {
  componentDidMount() {
    this.input.focus();
  }

  render() {
    return <input ref={(input) => (this.input = input)} placeholder="Enter text..." />;
  }
}

5. Eliminación de patrones de fábrica de módulos

Otra característica deprecada que se eliminará en React 19 son los patrones de fábrica de módulos (module pattern factories). Este patrón se utilizaba raramente y hacía que React fuera algo más grande y lento de lo necesario.

Los patrones de fábrica de módulos permitían a los desarrolladores crear componentes de manera menos convencional. Aquí tienes un ejemplo de cómo podrías estar utilizándolo:

function SettingsPanelFactory() {
  return {
    render() {
      return (
        <div className="settings-panel">
          <h2>Settings</h2>
          {/* other settings UI components */}
        </div>
      );
    }
  };
}

En este patrón, SettingsPanelFactory devuelve un objeto utilizando un método render en lugar de devolver JSX directamente.

Para cumplir con React 19, debes migrar los patrones de fábrica de módulos a funciones normales que devuelvan JSX directamente. Aquí tienes el ejemplo actualizado:

function SettingsPanel() {
  return (
    <div className="settings-panel">
      <h2>Settings</h2>
      {/* other settings UI components */}
    </div>
  );
}

6. Eliminación de la API createFactory

En React 19, se está eliminando React.createFactory. Este método se utilizaba con más frecuencia antes de que JSX estuviera ampliamente soportado. Permitía a los desarrolladores crear elementos React sin utilizar la sintaxis JSX.

Sin embargo, con la prevalencia de JSX, createFactory ha quedado obsoleto y puede sustituirse por código JSX más sencillo y legible.

Aquí tienes un ejemplo de uso de createFactory para crear un elemento button. Esto podría formar parte de un plugin personalizado de WordPress que genere dinámicamente elementos button en función de la entrada del usuario:

import { createFactory } from 'react';

const button = createFactory('button');

function CustomButton() {
  return button({ className: 'custom-button', type: 'button' }, 'Click Me');
}

Para actualizar este código para React 19, sustituye createFactory por JSX. Este cambio hace que el código sea más moderno, legible y fácil de mantener:

function CustomButton() {
  return <button className="custom-button" type="button">Click Me</button>;
}

7. Eliminación de react-test-renderer/shallow

React 19 elimina react-test-renderer/shallow para agilizar las utilidades de prueba y fomentar las mejores prácticas. En React 18, react-test-renderer/shallow se actualizó para volver a exportar react-shallow-renderer.

Anteriormente, podías haber utilizado react-test-renderer/shallow para crear pruebas de renderizado superficial para tus componentes React:

import ShallowRenderer from 'react-test-renderer/shallow';

test('MyComponent shallow render', () => {
  const renderer = new ShallowRenderer();
  renderer.render(<MyComponent />);
  const result = renderer.getRenderOutput();
  expect(result.type).toBe('div');
});

Para cumplir con React 19, necesitas instalar react-shallow-renderer:

npm install react-shallow-renderer --save-dev

Y actualizar tu importación:

import ShallowRenderer from 'react-shallow-renderer';

test('MyComponent shallow render', () => {
  const renderer = new ShallowRenderer();
  renderer.render(<MyComponent />);
  const result = renderer.getRenderOutput();
  expect(result.type).toBe('div');
});

El equipo de React recomienda migrar a la React Testing Library, que proporciona prácticas de prueba más sólidas al centrarse en cómo interactúan los usuarios con tus componentes.

Para ello, instala la @testing-library/react como dependencia de desarrollo:

npm install @testing-library/react --save-dev

A continuación, puedes probar el mismo componente utilizando este enfoque moderno:

import { render, screen } from '@testing-library/react';
import MyBlock from './MyBlock';

test('MyBlock renders correctly', () => {
  render(<MyBlock />);
  const element = screen.getByText('MyBlock content');
  expect(element).toBeInTheDocument();
});

Eliminación de deprecaciones en React DOM

React 19 ha introducido varios cambios importantes en React DOM, eliminando métodos que habían sido marcados como deprecados.  Esta sección describe estos cambios y te guía para actualizar tu código relacionado con el DOM.

1. Eliminación de la API react-dom/test-utils

La API react-dom/test-utilstambién se eliminará en React 19. Esto afecta a la forma de escribir pruebas para nuestros componentes React. En concreto, la utilidad act se ha trasladado de react-dom/test-utils al paquete react.

Además, se han eliminado la mayoría de las utilidades de react-dom/test-utils. A continuación te explicamos cómo adaptar tus pruebas para que se ajusten a estos cambios.

La utilidad act es esencial para garantizar que todas las actualizaciones relacionadas con tus pruebas se han procesado y aplicado al DOM. En React 19, debes importar act directamente de react en lugar de react-dom/test-utils.

// Before
import { act } from 'react-dom/test-utils';

// Now
import { act } from 'react';

El equipo de React también recomienda migrar tus pruebas a la React Testing Library para disfrutar de una experiencia de pruebas moderna y bien soportada. Aquí tienes algunos casos de uso comunes y cómo actualizarlos.

Se eliminará la utilidad renderIntoDocument. Puedes sustituirla por render desde @testing-library/react.

// Before
import { renderIntoDocument } from 'react-dom/test-utils';

renderIntoDocument(<Component />);

// Now
import { render } from '@testing-library/react';

render(<Component />);

Del mismo modo, se eliminará la utilidad Simulate para simular eventos. En su lugar, debes utilizar fireEvent de @testing-library/react, que envía un evento real sobre el elemento.

// Before
import { Simulate } from 'react-dom/test-utils';

const element = document.querySelector('button');
Simulate.click(element);

// Now
import { fireEvent } from '@testing-library/react';

const element = document.querySelector('button');
fireEvent.click(element);

Ten en cuenta que fireEvent envía un evento real, lo que significa que interactúa con el elemento de forma más natural que los eventos sintéticos creados por Simulate. Para comprender correctamente la biblioteca de pruebas de React, lee su documentación.

2. Eliminación de la API findDOMNode

Otro cambio significativo que llega a React 19 es la eliminación de ReactDOM.findDOMNode, que fue deprecado en React 16.6.0.

Esta función se utilizaba para acceder al nodo DOM subyacente de un componente React, pero tenía varios inconvenientes, como ser lenta de ejecutar, frágil a la refactorización y romper los niveles de abstracción.

En su lugar, debes utilizar las referencias DOM, que proporcionan una forma más fiable y eficiente de interactuar con los elementos DOM en tus componentes React.

Aquí tienes un ejemplo de uso de findDOMNode para seleccionar el texto de un campo de entrada cuando se monta el componente:

import { findDOMNode } from 'react-dom';

function AutoselectingInput() {
  useEffect(() => {
    const input = findDOMNode(this);
    input.select()
  }, []);

  render() {
    return <input defaultValue="Hello" />;
  }
}

Para actualizar este código para React 19, sustituye findDOMNode por un ref. Este cambio hace que el código sea más robusto y lo alinea con las prácticas modernas de React:

import React, { useEffect, useRef } from 'react';

function AutoselectingInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.select();
  }, []);

  return <input ref={inputRef} defaultValue="Hello" />;
}

3. Eliminación de la API de renderizado

Con React 19, se eliminará ReactDOM.render. Este fue deprecado en React en React 18.0.0 en favor de la API createRoot de react-dom/client, que proporciona una forma más eficiente y moderna de inicializar y renderizar aplicaciones React. Este cambio forma parte del esfuerzo continuo de React para optimizar y agilizar la biblioteca.

En una configuración típica de WordPress, puedes tener un bloque personalizado o un plugin que inicialice una aplicación React cuando el DOM esté listo. Antes utilizabas ReactDOM.render:

import { render } from 'react-dom';
render(<App />, document.getElementById('root'));

Con React 19, debes utilizar createRoot para inicializar y renderizar tu aplicación React:

import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);

4. Eliminación de la API unmountComponentAtNode

React 19 también elimina el método ReactDOM.unmountComponentAtNode, que fue deprecado en React 18.0.0. Este método se utilizaba para desmontar un componente React del DOM.

En React 19, debes migrar al uso del método root.unmount(), que está más alineado con la API actualizada para crear y renderizar aplicaciones React.

// Before
unmountComponentAtNode(document.getElementById('root'));

// Now
root.unmount();

5. Eliminación de la API hydrate

ReactDOM.hydrate fue deprecado en React 18 y se eliminará por completo en React 19.

El nuevo método de la API de cliente DOM de React, hydrateRoot, sustituye a ReactDOM.hydrate, proporcionando una forma más eficiente y moderna de activar y hacer interactivas las aplicaciones React renderizadas en el servidor.

En un contexto WordPress, podrías utilizar la renderización del lado del servidor (SSR) para entregar el contenido HTML inicial y conseguir cargas de página más rápidas. Para activar este contenido y convertirlo en una aplicación React interactiva, anteriormente usarías ReactDOM.hydrate:

import { hydrate } from 'react-dom';
import App from './App.js';

hydrate(
  <App />,
  document.getElementById('root')
);

Con React 19, debes utilizar hydrateRoot desde react-dom/client para la activación del contenido:

import { hydrateRoot } from 'react-dom/client';
import App from './App.js';

hydrateRoot(
  document.getElementById('root'),
  <App />
);

Eliminados tipos TypeScript deprecados

Los desarrolladores de WordPress suelen utilizar TypeScript para añadir seguridad de tipos y mejorar la calidad del código en los componentes de React. Con React 19, se han eliminado varios tipos TypeScript deprecaddos o se han reubicado en paquetes más relevantes.

Comprender estos cambios es crucial para garantizar que tu código base siga siendo robusto y compatible con la última versión de React.

Para facilitar la transición, el equipo de React ha creado una herramienta llamada types-react-codemodque puede actualizar automáticamente tu código base para gestionar estos cambios.

Para utilizarla, ejecuta el siguiente comando codemod, que incluye varias transformaciones para actualizar los tipos obsoletos.

npx types-react-codemod@latest preset-19 ./path-to-app

La herramienta también ofrece un modo interactivo en el que puedes elegir transformaciones específicas para aplicarlas:

? Pick transforms to apply (Press  to select,  to toggle all,  to invert selection, and  to proceed)
❯◯ context-any
◉ deprecated-react-type
◉ deprecated-sfc-element
◉ deprecated-sfc
◉ deprecated-stateless-component
◯ implicit-children
◯ useCallback-implicit-any

Veamos algunos cambios clave con ejemplos.

1. Limpieza de referencias (refs) requerida

Con React 19, las funciones de limpieza de ref mejoran la seguridad de tipos al obligar a realizar retornos explícitos en los callbacks ref. Los retornos implícitos pueden hacer que TypeScript malinterprete el valor de retorno.

// Before
 (instance = current)} />

// Now
 { instance = current }} />

2. useRef requiere un argumento

Antes, useRef podía invocarse sin argumentos, lo que podía dar lugar a problemas tipográficos. En React 19, useRef requiere un argumento para garantizar que las refs sean siempre mutables.

// Before — @ts-expect-error: Expected 1 argument but saw none
useRef();

// Now — correct usage with an argument
useRef(undefined);

3. Cambios en el tipo TypeScript de ReactElement

El tipo por defecto para ReactElement props ha cambiado de any a unknown, mejorando la seguridad de tipos al requerir un manejo explícito de los tipos desconocidos.

// Previously, this was 'any'
type Example = ReactElement["props"];

// Now, this is 'unknown'
type Example = ReactElement["props"];

Si tu código se basaba en any, debes actualizarlo para manejar unknown explícitamente o convertirlo a any.

Resumen

Como desarrolladores de WordPress, es crucial estar al día de los últimos avances de React. Esta guía te asegura que comprendes los distintos cambios que llegan a React para que puedas aplicarlos a tus proyectos de WordPress.

Un último dato: Con React 19, será necesaria la nueva transformación JSX. La buena noticia es que ya viene con WordPress 6.6. Si la nueva transformación no está activada, verás esta advertencia:

Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform

Lo único que tienes que hacer es dejar de utilizar las importaciones de React para las transformaciones JSX, pues ya no son necesarias.

¿Nos hemos dejado algo? ¡Compártelo con nosotros en la sección de comentarios!

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.