← Toute la documentation

Gérer l’état de l’éditeur dans React

Confiez le document courant à un seul propriétaire. Choisissez un état contrôlé lorsque le reste de votre application a besoin de chaque modification ; choisissez un éditeur non contrôlé lorsque vous avez surtout besoin de lire le contenu au moment de l’enregistrement. Ces exemples utilisent la liaison React publiée sur npm, en mode HTML.

Contrôlé : garder l’état local à jour

"use client";
import { useState } from "react";
import { RichTextEditor } from "@richscripts/richtexteditor/react";

export default function Composer() {
  const [html, setHtml] = useState("<p>Start writing...</p>");
  return <RichTextEditor
    value={html}
    onChange={(next) => {
      if (typeof next === "string") setHtml(next);
    }}
  />;
}

Conservez la valeur émise par l’éditeur comme valeur d’édition locale. Appliquez séparément un debounce à la persistance réseau, plutôt que de renvoyer volontairement une valeur plus ancienne à l’éditeur. Évitez de remplacer tout le document par une copie normalisée par le serveur après chaque enregistrement.

La liaison distingue les valeurs qu’elle a elle-même émises des remplacements externes. Elle ne rend pas pour autant chaque transformation faite par l’application sans danger pour la sélection. Un gestionnaire onChange qui reformate le HTML et renvoie un contenu différent demande à l’éditeur de remplacer le contenu pendant que quelqu’un tape.

Non contrôlé : lire le HTML courant lors de l’enregistrement

"use client";
import { useRef, useState } from "react";
import { RichTextEditor } from "@richscripts/richtexteditor/react";
import type { RichTextEditorReactHandle } from "@richscripts/richtexteditor/react";

export default function Draft({ initialHtml, onSave }: {
  initialHtml: string;
  onSave: (html: string) => void;
}) {
  const editorRef = useRef<RichTextEditorReactHandle>(null);
  const [ready, setReady] = useState(false);
  return <>
    <RichTextEditor ref={editorRef} defaultValue={initialHtml}
      onReady={() => setReady(true)} />
    <button type="button" disabled={!ready} onClick={() => {
      if (editorRef.current?.getEditor()) {
        onSave(editorRef.current.getHTMLCode());
      }
    }}>Save</button>
  </>;
}

defaultValue initialise le document ; ce n’est pas un moyen de transmettre les modifications ultérieures à un éditeur déjà monté. La ref expose getHTMLCode(). La vérification de disponibilité empêche un enregistrement prématuré de traiter un éditeur non encore initialisé comme un document vide.

Cet exemple transmet le HTML au callback de votre application ; il n’implémente ni la persistance, ni la fin des envois, ni la reprise après une erreur d’enregistrement. Si les images sont activées, utilisez la séquence d’envoi et d’enregistrement avant de lire le HTML final. Validez et nettoyez le contenu soumis sur le serveur.

Changer de document et traiter les réponses du serveur en toute sécurité

  • Utilisez une identité de document stable. Une key fondée sur le HTML courant ou sur un nombre aléatoire remonte l’éditeur pendant l’édition.
  • Une key délibérément fondée sur l’identifiant du document peut démarrer un nouvel éditeur pour un autre document. Faites confirmer ou enregistrez un brouillon modifié avant de changer ; un remontage abandonne l’état de l’instance, comme la sélection et l’historique d’annulation.
  • Si vous chargez les documents de façon asynchrone, ignorez ou interrompez la réponse concernant un document qui n’est plus sélectionné.
  • Suivez une révision du document lors de l’enregistrement. Une réponse tardive doit mettre à jour l’état d’enregistrement de sa propre révision, et non écraser un brouillon plus récent. Des vérifications de révision côté serveur sont nécessaires pour détecter l’enregistrement concurrent d’un autre utilisateur.
  • Ne passez pas du mode contrôlé au mode non contrôlé en cours de session. Choisissez le modèle à l’ouverture du document.

Montage et Strict Mode

Utilisez le wrapper React fourni plutôt que de créer un second éditeur sur le même hôte. Si vous écrivez votre propre wrapper, créez l’éditeur une fois l’hôte présent, détachez les écouteurs qui vous appartiennent et détruisez l’instance qui vous appartient lors du nettoyage. Ignorez une initialisation asynchrone qui se termine après le démontage.

Le Strict Mode de React peut exécuter un cycle supplémentaire de mise en place et de nettoyage en développement. Gardez-le activé pendant que vous vérifiez le comportement du cycle de vie. Pour Next.js, suivez le guide d’intégration en composant client ; afficher du contenu enregistré et monter un éditeur interactif sont deux questions distinctes.

Liste de vérification pour le dépannage

  • Le curseur saute : vérifiez les keys qui changent, les composants recréés, les appels répétés à setHTMLCode() et les valeurs contrôlées transformées.
  • La saisie disparaît : vérifiez les valeurs périmées provenant de callbacks différés, de réponses d’enregistrement et de chargements de documents.
  • L’enregistrement manque la dernière modification : lisez la ref de l’éditeur au moment de la soumission au lieu de supposer qu’une notification de modification différée a déjà mis à jour l’état React.
  • Barres d’outils en double : vérifiez les initialisations et nettoyages en double, y compris lors des changements de route et de la réouverture de fenêtres modales.
  • Les grands brouillons semblent lents : profilez séparément la sérialisation HTML, le rendu de l’aperçu et les enregistrements réseau.
  • La saisie IME ne fonctionne plus : testez la composition en chinois ou en japonais sans réécrire le contenu pendant la composition, et vérifiez l’annulation une fois le texte validé.

Ensuite : diagnostiquer pas à pas les sauts de curseur, installer la liaison React, ou essayer l’envoi de formulaire et l’enregistrement et le chargement.

Références : React Strict Mode et la conservation et la réinitialisation de l’état.