Als WordPress ontwikkelaars integreren we vaak custom React componenten in onze thema’s en plugins om dynamische en responsieve gebruikersinterfaces te maken.

Met de komende release van React 19 is het cruciaal om je voor te bereiden op veranderingen en afschrijvingen (deprecations) die van invloed kunnen zijn op onze bestaande codebases. WordPress 6.6, die op 16 juli wordt uitgebracht, bevat React 18.3. Deze versie is bijna identiek aan 18.2, maar voegt waarschuwingen toe voor afgeschreven functies om je voor te bereiden op React 19.

Het aanpakken van deze afschrijvingen is essentieel om compatibiliteit met React 19 te garanderen, en ze negeren kan leiden tot bugs of problemen in je custom blokken, plugins of thema’s wanneer React 19 wordt uitgebracht en opgenomen in WordPress.

Dit artikel beschrijft elke deprecatie, geeft codevoorbeelden en begeleidt je bij het vervangen van afgeschreven functies om de functionaliteit soepel te houden.

Verwijderde afschrijvingen in React

Verschillende afgeschreven API’s en functies zijn verwijderd om de React bibliotheek te stroomlijnen en best practices aan te moedigen. Deze sectie behandelt de belangrijkste wijzigingen en hoe je je code dienovereenkomstig kunt bijwerken.

1. Verwijdering van defaultProps voor functiecomponenten

React 19 verwijdert defaultProps voor functiecomponenten ten gunste van ES6 standaardparameters. Volgens het WordPress team wordt deze afschrijving het meest gebruikt in plugins en thema’s.

Als WordPress ontwikkelaar zou je defaultProps kunnen gebruiken om standaardwaarden te bieden voor props in je functiecomponenten, om ervoor te zorgen dat componenten zich correct gedragen, zelfs als bepaalde props niet worden doorgegeven.

Hier zie je hoe je huidige code eruit zou kunnen zien met defaultProps:

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

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

In dit voorbeeld heeft een CustomButton component standaardwaarden voor label en color die worden verstrekt door defaultProps. In React 19 zal dit een waarschuwingsfout opleveren en je aansporen om in plaats daarvan ES6 standaardparameters te gebruiken.

Hier is de bijgewerkte code met ES6 standaardparameters:

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

Door ES6-standaardparameters te gebruiken, staan de standaardwaarden nu direct in de functiehandtekening, waardoor de code gemakkelijker te lezen en te onderhouden is.

2. Verwijdering van propTypes voor functiecomponenten

propTypes was afgeschreven in React 15.5.0 en zal volledig worden verwijderd in het React pakket van v19. Als je propTypes gebruikt, is het aan te raden om te migreren naar TypeScript of een andere oplossing voor typecontrol.

Je hebt misschien propTypes gebruikt om de props te valideren die zijn doorgegeven aan je functiecomponenten om ervoor te zorgen dat ze de juiste types en waarden ontvangen. Bijvoorbeeld:

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

Vandaag kun je TypeScript gaan gebruiken voor deze typecontrols:

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

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

3. Verwijdering van verouderde context (contextTypes en getChildContext)

Gezien de langdurige aard van veel plugins en codebases in WordPress, gebruik je misschien nog steeds de oude contextTypes en getChildContext API’s in je klasse componenten. Deze API’s werden gebruikt om gegevens van een ouder component door te geven aan zijn descendants zonder expliciet props door te geven op elk niveau.

Het is echter belangrijk om op te merken dat Legacy Context in React 16.6.0 is afgeschreven en in React v19 zal worden verwijderd. Deze verandering is bedoeld om React iets kleiner en sneller te maken, omdat de Legacy Context API subtiele bugs had die vaak gemakkelijk over het hoofd te zien waren.

De legacy methode is vervangen door de nieuwe contextType API.

Hier is een voorbeeld van hoe je de verouderde Context API kunt gebruiken in een WordPress plugin om globale instellingen, zoals de sitetitel, door te geven van een ouder component naar een child component zonder 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>;
  }
}

De moderne benadering gebruikt daarentegen de methode createContext. Dit is de methode die je moet gebruiken als je je voorbereidt op 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. Verwijdering van string refs

Het gebruik van string refs was ooit een veelgebruikte manier om toegang te krijgen tot een DOM element in React componenten. Ze worden echter als legacy beschouwd sinds React 16.3.0 en zullen worden verwijderd in v19.

Hoewel string refs eenvoudig waren, hadden ze verschillende problemen, zoals potentiële naamgevingsconflicten en een gebrek aan flexibiliteit.

Neem een voorbeeld van het gebruik van string refs in een WordPress custom blok. Stel je voor dat je een aangepast Gutenberg blok hebt dat een invoerveld bevat, en je wilt dat het invoerveld automatisch wordt gefocust wanneer het blok wordt toegevoegd aan de editor. Dit is hoe je dit gedaan zou kunnen hebben met behulp van string refs:

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

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

Om je voor te bereiden op React 19 moet je string refs vervangen door callback refs of de React.createRef API. Hier is hetzelfde voorbeeld met een callback ref:

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

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

5. Verwijdering van module pattern factories

Een andere afgeschreven functie die zal worden verwijderd in React 19 zijn module pattern factories. Deze pattern werd zelden gebruikt en zorgde ervoor dat React iets groter en langzamer werd dan nodig.

Module pattern factories stelden ontwikkelaars in staat om componenten minder conventioneel te maken. Hier is een voorbeeld van hoe je het misschien gebruikt:

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

In deze pattern retourneert SettingsPanelFactory een object met behulp van een render methode in plaats van direct JSX terug te geven.

Om te voldoen aan React 19 moet je module pattern factories migreren naar reguliere functies die JSX direct retourneren. Hier is het bijgewerkte voorbeeld:

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

6. Verwijdering van createFactory API

In React 19 wordt React.createFactory verwijderd. Deze methode werd vaker gebruikt voordat JSX breed werd ondersteund. Het stelde ontwikkelaars in staat om React elementen te maken zonder JSX syntax te gebruiken.

Nu JSX steeds meer wordt gebruikt, is createFactory echter verouderd en kan het worden vervangen door eenvoudigere, beter leesbare JSX code.

Hier is een voorbeeld van het gebruik van createFactory om een button element te maken. Dit zou onderdeel kunnen zijn van een aangepaste WordPress plugin die dynamisch button elementen genereert op basis van gebruikersinvoer:

import { createFactory } from 'react';

const button = createFactory('button');

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

Om deze code bij te werken voor React 19, vervang je createFactory door JSX. Deze wijziging maakt de code moderner, leesbaarder en beter onderhoudbaar:

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

7. Verwijdering van react-test-renderer/shallow

React 19 verwijdert react-test-renderer/shallow om de testutility te stroomlijnen en best practices aan te moedigen. In React 18 werd react-test-renderer/shallow bijgewerkt om opnieuw te exporteren react-shallow-renderer.

Voorheen gebruikte je react-test-renderer/shallow om ondiepe rendertests te maken voor je React-componenten:

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

Om aan React 19 te voldoen, moet je het volgende installeren react-shallow-renderer:

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

En je import bijwerken:

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

Het React team raadt aan om te migreren naar de React Testing Library, die robuustere testpraktijken biedt door zich te richten op de interactie tussen gebruikers en je componenten.

Om dit te doen installeer je de @testing-library/react bibliotheek als een dev-afhankelijkheid:

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

Vervolgens kun je dezelfde component testen met deze moderne aanpak:

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

Verwijderde afschrijvingen in React DOM

React DOM is ook veranderd in React 19, waarbij bepaalde afgeschreven methoden zijn verwijderd. Deze sectie beschrijft deze wijzigingen en begeleidt je bij het bijwerken van je DOM gerelateerde code.

1. Verwijdering van react-dom/test-utils API

De react-dom/test-utils API wordt verwijderd in React 19. Dit heeft gevolgen voor de manier waarop we tests schrijven voor onze React componenten. Specifiek is de utilityact verplaatst van react-dom/test-utils naar het pakket react.

Daarnaast zijn de meeste andere utility van react-dom/test-utils verwijderd. Hier lees je hoe je je tests kunt aanpassen aan deze veranderingen.

De utility  act is essentieel om ervoor te zorgen dat alle updates met betrekking tot je tests zijn verwerkt en toegepast op de DOM. In React 19 moet je act rechtstreeks importeren vanuit react in plaats van react-dom/test-utils.

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

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

Het React team raadt ook aan om je tests te migreren naar de React Testing Library voor een moderne en goed ondersteunde testervaring. Hier zijn enkele veelvoorkomende use cases en hoe je ze kunt bijwerken.

De utility renderIntoDocument wordt verwijderd. Je kunt het vervangen door render van @testing-library/react.

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

renderIntoDocument(<Component />);

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

render(<Component />);

Op dezelfde manier wordt het utility Simulate voor het simuleren van events verwijderd. In plaats daarvan moet je fireEvent van @testing-library/react gebruiken, dat een echt event op het element afstuurt.

// 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);

Houd er rekening mee dat fireEvent een echt event verzendt, wat betekent dat het een natuurlijkere interactie heeft met het element dan de synthetische gebeurtenissen die zijn gemaakt door Simulate. Lees de documentatie van de React testbibliotheek om deze goed te begrijpen.

2. Verwijdering van findDOMNode API

Een andere belangrijke verandering in React 19 is de verwijdering van ReactDOM.findDOMNode, die in React 16.6.0 niet meer werd gebruikt.

Deze functie werd gebruikt om toegang te krijgen tot de onderliggende DOM-node van een React-component, maar had verschillende nadelen, zoals traagheid bij het uitvoeren, kwetsbaarheid voor refactoring en het doorbreken van abstractieniveaus.

In plaats daarvan kun je beter DOM refs gebruiken, die een betrouwbaardere en efficiëntere manier bieden voor interactie met DOM-elementen in je React-componenten.

Hier is een voorbeeld van het gebruik van findDOMNode om de tekst in een invoerveld te selecteren wanneer het component mount:

import { findDOMNode } from 'react-dom';

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

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

Om deze code bij te werken voor React 19, vervang je findDOMNode door ref. Deze wijziging maakt de code robuuster en stemt hem af op moderne React-praktijken:

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

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

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

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

3. Verwijdering van render API

Met React 19 wordt ReactDOM.render verwijderd. Deze methode werd afgeschreven in React 18.0.0 ten gunste van createRoot API van react-dom/client, die een efficiëntere en modernere manier biedt om React applicaties te initialiseren en renderen. Deze verandering maakt deel uit van de voortdurende inspanningen van React om de bibliotheek te stroomlijnen en te optimaliseren.

In een typische WordPress opstelling heb je misschien een custom blok of een plugin die een React app initialiseert als de DOM klaar is. Voorheen gebruikte je ReactDOM.render:

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

Met React 19 moet je createRoot gebruiken om je React applicatie te initialiseren en renderen:

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

4. Verwijdering van unmountComponentAtNode API

React 19 verwijdert ook de methode ReactDOM.unmountComponentAtNode, die afgeschreven werd in React 18.0.0. Deze methode werd gebruikt om een React component te unmounten van het DOM.

In React 19 moet je overstappen op de methode root.unmount(), die beter aansluit bij de bijgewerkte API voor het maken en hydraten van roots.

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

// Now
root.unmount();

5. Verwijdering van hydrate API

ReactDOM.hydrate was deprecated in React 18 en zal volledig worden verwijderd in React 19.

De nieuwe methode van de React DOM client API, hydrateRoot, vervangt ReactDOM.hydrate en biedt een efficiëntere en modernere manier om server-rendered React applicaties te hydrateren.

In een WordPress context zou je server-side rendering (SSR) kunnen gebruiken om initiële HTML inhoud te leveren voor het sneller laden van pagina’s. Om deze inhoud te hydraten in een interactieve React applicatie, gebruikte je voorheen ReactDOM.hydrate:

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

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

Met React 19 moet je hydrateRoot van react-dom/client gebruiken voor hydrating:

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

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

Afgeschreven TypeScript types verwijderd

WordPress ontwikkelaars gebruiken vaak TypeScript om typeveiligheid toe te voegen en de kwaliteit van de code in React componenten te verbeteren. Met React 19 zijn verschillende afgeschreven TypeScript types verwijderd of verplaatst naar relevantere pakketten.

Inzicht in deze wijzigingen is cruciaal om ervoor te zorgen dat je codebase robuust en compatibel blijft met de nieuwste React versie.

Om te helpen bij de overgang heeft het React team een tool beschikbaar gesteld met de naam types-react-codemoddat je codebase automatisch kan bijwerken om deze wijzigingen te verwerken.

Om het te gebruiken voer je het volgende codemod commando uit, dat verschillende transformaties bevat om verouderde types bij te werken.

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

De utility biedt ook een interactieve modus waarin je specifieke transformaties kunt kiezen om toe te passen:

? 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

Laten we eens kijken naar enkele belangrijke veranderingen met voorbeelden.

1. Ref opruiming vereist

In React 19 verbeteren ref opruimfuncties de typeveiligheid door expliciete retours in ref callbacks af te dwingen. Impliciet teruggeven kan TypeScript de retourwaarde verkeerd laten interpreteren.

// Before
 (instance = current)} />

// Now
 { instance = current }} />

2. useRef vereist een argument

Voorheen kon useRef zonder argumenten worden gecalld, wat tot potentiële typeproblemen leidde. In React 19 vereist useRef een argument om ervoor te zorgen dat refs altijd mutebaar zijn.

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

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

3. Wijzigingen in het ReactElement TypeScript

Het standaardtype voor ReactElement props is veranderd van any in unknown, waardoor de typeveiligheid is verbeterd door expliciete afhandeling van onbekende typen te vereisen.

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

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

Als je code vertrouwde op any, moet je deze bijwerken om unknown expliciet te behandelen of te casten naar any.

Samenvatting

Voor WordPress ontwikkelaars is het cruciaal om op de hoogte te blijven van de laatste ontwikkelingen in React. Deze gids zorgt ervoor dat je de verschillende veranderingen in React begrijpt, zodat je ze kunt toepassen in je WordPress projecten.

Nog een laatste stukje informatie: Met React 19 zal de nieuwe JSX transform nodig zijn. Het goede nieuws is dat deze al wordt meegeleverd met WordPress 6.6. Als de nieuwe transform niet is ingeschakeld, zie je deze waarschuwing:

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

Je hoeft alleen maar te stoppen met het gebruik van React imports voor JSX transformaties, omdat ze niet langer nodig zijn.

Hebben we iets gemist? Deel het met ons in de comments!

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.