Come sviluppatori WordPress, spesso integriamo componenti React personalizzati nei nostri temi e plugin per creare interfacce utente dinamiche e reattive.

Con l’imminente rilascio di React 19, è fondamentale prepararsi alle modifiche e alle deprecazioni che potrebbero avere un impatto sulle nostre basi di codice esistenti. WordPress 6.6, che verrà rilasciato il 16 luglio, include React 18.3. Questa versione è quasi identica alla 18.2 ma aggiunge avvisi per le funzionalità deprecate per aiutare gli utenti a prepararsi a React 19.

Affrontare queste deprecazioni è essenziale per garantire la compatibilità con React 19; ignorarle può portare a bug o problemi nei blocchi personalizzati, plugin o temi quando React 19 verrà rilasciato e incluso in WordPress.

Questo articolo illustra ogni deprecazione, fornisce esempi di codice e guida nella sostituzione delle funzioni deprecate per mantenere la funzionalità senza problemi.

Deprecazioni rimosse in React

Diverse API e funzionalità deprecate sono state rimosse per snellire la libreria React e incoraggiare le best practice. Questa sezione illustra i principali cambiamenti e come aggiornare il vostro codice di conseguenza.

1. Rimozione di defaultProps per i componenti funzionali

React 19 rimuoverà defaultProps per i componenti delle funzioni a favore dei parametri predefiniti ES6. Secondo il team di WordPress, questa deprecazione è più comunemente utilizzata nei plugin e nei temi.

Come sviluppatori di WordPress, potreste utilizzare defaultProps per fornire valori predefiniti per i prop nei vostri componenti funzionali, assicurandovi che i componenti si comportino correttamente anche se alcuni prop non vengono passati.

Ecco come potrebbe apparire il vostro codice attuale con defaultProps:

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

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

In questo esempio, un componente CustomButton ha i valori predefiniti di label e color forniti da defaultProps. Con React 19, questo errore verrà segnalato, invitandovi a utilizzare invece i parametri predefiniti di ES6.

Ecco il codice aggiornato con i parametri predefiniti ES6:

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

Utilizzando i parametri predefiniti ES6, i valori predefiniti sono ora direttamente nella firma della funzione, rendendo il codice più facile da leggere e da mantenere.

2. Rimozione di propTypes per i componenti delle funzioni

propTypes è stato deprecato in React 15.5.0 e sarà completamente rimosso anche nel pacchetto React nella versione 19. Se utilizzate propTypes, vi consigliamo di migrare a TypeScript o a un’altra soluzione di controllo dei tipi.

Potreste aver utilizzato propTypes per convalidare i prop passati ai vostri componenti funzionali per assicurarvi che ricevano i tipi e i valori corretti. Ad esempio:

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,
};

Oggi potete iniziare a usare TypeScript per questi controlli di tipo:

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

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

3. Rimozione dei contesti legacy (contextTypes e getChildContext)

Data la natura di lunga data di molti plugin e codebase di WordPress, potreste ancora utilizzare le API legacy contextTypes e getChildContext nei vostri componenti di classe. Queste API venivano utilizzate per passare i dati da un componente genitore ai suoi discendenti senza passare esplicitamente i prop a ogni livello.

Tuttavia, è importante notare che il Legacy Context è stato deprecato in React 16.6.0 e sarà rimosso in React v19. Questo cambiamento ha lo scopo di rendere React leggermente più piccolo e più veloce, in quanto l’API Legacy Context presentava dei piccoli bug che spesso erano facili da ignorare.

Il metodo legacy è stato sostituito dalla nuova API contextType.

Ecco un esempio di come potreste utilizzare l’API Context deprecata in un plugin di WordPress per passare le impostazioni globali, come il titolo del sito, da un componente parent a un componente child senza 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>;
  }
}

Al contrario, l’approccio moderno utilizza il metodo createContext. Questo è il metodo da adottare per prepararsi a 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. Rimozione delle stringhe di riferimento

L’uso delle stringhe di riferimento (string refs) era un tempo un modo comune per accedere a un elemento DOM nei componenti React. Tuttavia, sono considerati una legacy già da React 16.3.0 e saranno rimossi nella versione 19.

Sebbene gli string refs fossero semplici, presentavano diversi problemi, come i potenziali conflitti di denominazione e la mancanza di flessibilità.

Consideriamo un esempio di utilizzo delle stringhe di riferimento in un blocco personalizzato di WordPress. Immaginiamo di avere un blocco personalizzato di Gutenberg che include un campo di input, e di volere che il campo di input venga focalizzato automaticamente quando il blocco viene aggiunto all’editor. Ecco come avremmo potuto farlo utilizzando le stringhe di riferimento:

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

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

Per prepararci a React 19, dovremo sostituire i riferimenti a stringhe con callback refs o con l’API React.createRef. Ecco lo stesso esempio utilizzando una callback ref:

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

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

5. Rimozione delle module pattern factories

Un’altra funzione deprecata che verrà rimossa in React 19 è quella delle module pattern factories. Questo pattern veniva utilizzato raramente e rendeva React leggermente più grande e più lento del necessario.

Le module pattern factories permettevano agli sviluppatori di creare componenti in modo meno convenzionale. Ecco un esempio di come potreste usarlo:

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

In questo pattern, SettingsPanelFactory restituisce un oggetto utilizzando un metodo render piuttosto che restituire direttamente JSX.

Per essere conforme a React 19, dovrete migrare le fabbriche di moduli a funzioni regolari che restituiscano direttamente JSX. Ecco l’esempio aggiornato:

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

6. Rimozione dell’API createFactory

In React 19, React.createFactory è stato rimosso. Questo metodo era molto utilizzato prima che JSX diventasse ampiamente supportato. Consentiva agli sviluppatori di creare elementi React senza utilizzare la sintassi JSX.

Tuttavia, con la diffusione di JSX, createFactory è diventato obsoleto e può essere sostituito con un codice JSX più semplice e leggibile.

Ecco un esempio di utilizzo di createFactory per creare un elemento button. Questo potrebbe far parte di un plugin WordPress personalizzato che genera dinamicamente elementi button in base agli input dell’utente:

import { createFactory } from 'react';

const button = createFactory('button');

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

Per aggiornare questo codice a React 19, sostituite createFactory con JSX. Questa modifica rende il codice più moderno, leggibile e manutenibile:

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

7. Rimozione di react-test-renderer/shallow

React 19 rimuove react-test-renderer/shallow per semplificare le utility di test e incoraggiare le best practice. In React 18, react-test-renderer/shallow è stato aggiornato per esportare nuovamente react-shallow-renderer.

In precedenza, era possibile utilizzare react-test-renderer/shallow per creare test di rendering superficiale per i componenti 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');
});

Per conformarsi a React 19, è necessario installare react-shallow-renderer:

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

E aggiornare l’importazione:

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');
});

Il team di React consiglia di migrare alla React Testing Library, che offre pratiche di test più robuste concentrandosi sul modo in cui gli utenti interagiscono con i vostri componenti.

Per farlo, installate la libreria @testing-library/react come dipendenza dev:

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

Successivamente, potete testare lo stesso componente utilizzando questo approccio 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();
});

Eliminazione delle deprecazioni in React DOM

Anche React DOM è cambiato in React 19, con la rimozione di alcuni metodi deprecati. Questa sezione illustra questi cambiamenti e guida nell’aggiornamento del codice relativo al DOM.

1. Rimozione dell’API react-dom/test-utils

L’API react-dom/test-utils sarà anch’essa rimossa in React 19. Questo ha un impatto sul modo in cui scriviamo i test per i nostri componenti React. In particolare, l’utility act è stata spostata da react-dom/test-utils al pacchetto react.

Inoltre, la maggior parte delle utility di react-dom/test-utils sono state rimosse. Ecco come adattare i vostri test per conformarsi a questi cambiamenti.

L’utility act è essenziale per garantire che tutti gli aggiornamenti relativi ai vostri test siano stati elaborati e applicati al DOM. In React 19, dovreste importare act direttamente da react invece di react-dom/test-utils.

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

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

Il team di React raccomanda anche di migrare i vostri test alla React Testing Library per un’esperienza di test moderna e ben supportata. Ecco alcuni casi d’uso comuni e come aggiornarli.

L’utility renderIntoDocument verrà rimossa. Potrete sostituirla con render da @testing-library/react.

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

renderIntoDocument(<Component />);

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

render(<Component />);

Allo stesso modo, l’utility Simulate per la simulazione degli eventi sarà rimossa. Dovrete invece utilizzare fireEvent da @testing-library/react, che invia un evento reale sull’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);

Tenete presente che fireEvent invia un evento reale, il che significa che interagisce con l’elemento in modo più naturale rispetto agli eventi sintetici creati da Simulate. Per capire bene la libreria di testing di React, leggete la sua documentazione.

2. Rimozione dell’API findDOMNode

Un altro cambiamento significativo in arrivo in React 19 è la rimozione di ReactDOM.findDOMNode, che è stata deprecata in React 16.6.0.

Questa funzione veniva utilizzata per accedere al nodo DOM sottostante di un componente React, ma presentava diversi inconvenienti, come la lentezza di esecuzione, la fragilità nel refactoring e la rottura dei livelli di astrazione.

Dovreste invece utilizzare le DOM refs, che offrono un modo più affidabile ed efficiente per interagire con gli elementi DOM nei vostri componenti React.

Ecco un esempio di utilizzo di findDOMNode per selezionare il testo in un campo di input quando il componente viene montato:

import { findDOMNode } from 'react-dom';

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

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

Per aggiornare questo codice per React 19, sostituite findDOMNode con ref. Questa modifica rende il codice più robusto e lo allinea alle moderne pratiche di React:

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

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

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

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

3. Rimozione dell’API di rendering

Con React 19, ReactDOM.render sarà rimosso. Questo metodo è stato deprecato in React 18.0.0 in favore dell’API createRoot di react-dom/client, che fornisce un modo più efficiente e moderno per inizializzare e renderizzare le applicazioni React. Questo cambiamento fa parte del continuo sforzo di React per semplificare e ottimizzare la libreria.

In una tipica configurazione di WordPress, potreste avere un blocco personalizzato o un plugin che inizializza un’applicazione React quando il DOM è pronto. In precedenza, si utilizzava ReactDOM.render:

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

Con React 19, dovrete utilizzare createRoot per inizializzare e renderizzare la vostra applicazione React:

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

4. Rimozione dell’API unmountComponentAtNode

React 19 rimuove anche il metodo ReactDOM.unmountComponentAtNode, deprecato in React 18.0.0. Questo metodo veniva utilizzato per smontare un componente React dal DOM.

In React 19, dovreste migrare all’uso del metodo root.unmount(), che è più in linea con l’API aggiornata per la creazione e l’hydrating delle root.

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

// Now
root.unmount();

5. Rimozione dell’API hydrate

ReactDOM.hydrate è stato deprecato in React 18 e sarà completamente rimosso in React 19.

Il nuovo metodo dell’API client di React DOM, hydrateRoot, sostituisce ReactDOM.hydrate, offrendo un modo più efficiente e moderno per eseguire l’hydrate le applicazioni React renderizzate dal server.

In un contesto WordPress, potreste utilizzare il rendering lato server (SSR) per fornire il contenuto HTML iniziale e velocizzare il caricamento della pagina. Per eseguire l’hydrate di questo contenuto in un’applicazione React interattiva, in precedenza si utilizzava ReactDOM.hydrate:

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

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

Con React 19, dovrete utilizzare hydrateRoot da react-dom/client per l’hydrate:

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

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

Tipi TypeScript deprecati rimossi

Gli sviluppatori di WordPress utilizzano spesso TypeScript per aggiungere sicurezza ai tipi e migliorare la qualità del codice nei componenti React. Con React 19, diversi tipi di TypeScript deprecati sono stati rimossi o riposizionati in pacchetti più pertinenti.

Comprendere questi cambiamenti è fondamentale per garantire che la propria base di codice rimanga robusta e compatibile con l’ultima versione di React.

Per facilitare la transizione, il team di React ha messo a disposizione uno strumento chiamato types-react-codemodche può aggiornare automaticamente la base di codice per gestire questi cambiamenti.

Per utilizzarlo, eseguite il comando codemod qui sotto, che include diverse trasformazioni per aggiornare i tipi deprecati.

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

Lo strumento offre anche una modalità interattiva in cui scegliere le trasformazioni specifiche da applicare:

? 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

Diamo un’occhiata ad alcuni cambiamenti chiave con degli esempi.

1. Ref cleanup obbligatoria

Con React 19, le funzioni di cleanup di ref migliorano la sicurezza dei tipi imponendo il ritorno esplicito nelle callback di ref. I ritorni impliciti possono indurre TypeScript a interpretare erroneamente il valore di ritorno.

// Before
 (instance = current)} />

// Now
 { instance = current }} />

2. useRef richiede un argomento

In precedenza, useRef poteva essere richiamato senza argomenti, causando potenziali problemi di tipo. In React 19, useRef richiede un argomento per garantire che i ref siano sempre mutabili.

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

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

3. Modifiche al tipo di ReactElement TypeScript

Il tipo predefinito per i prop di ReactElement è cambiato da any a unknown, migliorando la sicurezza dei tipi grazie alla necessità di gestire esplicitamente i tipi sconosciuti.

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

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

Se il vostro codice si basava su any, dovrete aggiornarlo per gestire unknown in modo esplicito o per eseguire il cast di any.

Riepilogo

Per gli sviluppatori di WordPress è fondamentale rimanere aggiornati sulle ultime novità di React. Questa guida permette di comprendere i vari cambiamenti in arrivo per React in modo da poterli applicare ai vostri progetti WordPress.

Un’ultima informazione: Con React 19 sarà necessaria la nuova trasformazione JSX. La buona notizia è che è già disponibile con WordPress 6.6. Se il nuovo trasformatore non è abilitato, vedrete questo avviso:

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

(L’applicazione (o una delle sue dipendenze) utilizza una trasformazione JSX obsoleta. Aggiorna alla trasformazione JSX moderna per ottenere prestazioni più veloci: https://react.dev/link/new-jsx-transform)

Tutto quello che dovrete fare è smettere di usare le importazioni di React per le trasformazioni JSX, perché non sono più necessarie.

Ci siamo persi qualcosa? Condividetelo con noi nella sezione commenti!

Joel Olawanle Kinsta

Joel è uno Frontend developer che lavora in Kinsta come redattore tecnico. È un insegnante appassionato che ama l'open source e ha scritto oltre 200 articoli tecnici principalmente su JavaScript e i suoi framework.