CodeMirror mount-timing in React

Definitie

CodeMirror 6 initialiseert zijn interne document op het moment dat de React-component mount. Als de initiële content op dat moment nog niet beschikbaar is (async load), wordt de editor aangemaakt met een leeg document en blijft leeg — ook als de prop later een waarde krijgt.

Context

Dit probleem doet zich voor wanneer content asynchroon geladen wordt (bijvoorbeeld via fetch, callTool, of IndexedDB) en de initialContent-prop pas na de mount-aanroep zijn waarde krijgt. Omdat CodeMirror zijn state intern beheert en niet via React re-renders, heeft een prop-update na mount geen effect.

Kernpunten

Symptoom: Editor is leeg ondanks dat initialContent correct ingesteld wordt.

Oorzaak: useEffect([], []) (mount-only) maakt de EditorView aan met de waarde van doc op dat moment. Latere wijzigingen in de prop worden genegeerd.

Oplossing — loaded-flag: Render de component pas nadat content beschikbaar is:

const [loaded, setLoaded] = useState(false);
const [initialContent, setInitialContent] = useState('');
 
useEffect(() => {
  async function load() {
    const text = await fetchContent();
    setInitialContent(text);
    setLoaded(true);
  }
  load();
}, [assetId]);
 
// In JSX:
{loaded && <MarkdownEditor initialContent={initialContent} />}

Alternatief — setContent imperatively: Gebruik een ref met een setContent-methode die dispatch aanroept:

setContent: (text: string) => {
  view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: text } });
}

Dit vereist extra logica om te voorkomen dat de gebruiker ondertussen al getypt heeft.

Aanbeveling: De loaded-flag is eenvoudiger en voorkomt een flash van lege editor. De imperatieve aanpak is beter als content ook tijdens een sessie opnieuw geladen moet worden.

Bijwerking van de loaded-flag: Extensies die afhankelijk zijn van de content (zoals isTranscript-detectie) moeten óók na de load bepaald worden, niet bij het openen van het asset. Zo voorkom je mismatch tussen extensions en weergegeven tekst.

Verbanden

Bronnen

CodeMirror 6 documentatie: https://codemirror.net/docs/guide/

Sessie-herkomst