Skip to content

Bug: TypeError: Cannot read properties of null (reading 'style') when component unmounts before script loads #100

@KieranP

Description

@KieranP

(disclaimer: issue description and reproducible test case produced by Claude Open 4.7, but verified by a human for accuracy)

Summary

If an Editor instance unmounts before tinymce.min.js finishes loading, the script's onload later runs an orphaned init() callback and throws TypeError: Cannot read properties of null (reading 'style') at Editor.svelte line 182 (element!.style.visibility = '').

Minimal reproduction

  1. Throttle the network in DevTools to "Slow 3G" (or anything that makes the TinyMCE script take >100ms).
  2. Mount the component below — it unmounts itself after 50ms.
  3. Observe the uncaught TypeError when the script eventually loads.
<script lang="ts">
  import Editor from '@tinymce/tinymce-svelte';

  let mounted = $state(true);

  // Unmount before the TinyMCE script can finish loading.
  // Any value smaller than the script's load time will reproduce.
  $effect(() => {
    const id = setTimeout(() => { mounted = false; }, 50);
    return () => clearTimeout(id);
  });
</script>

{#if mounted}
  <Editor
    apiKey="no-api-key"
    channel="8"
  />
{/if}

<!--
  Expected: clean unmount, no console errors.
  Actual: when the TinyMCE script finishes loading, an uncaught
          TypeError: Cannot read properties of null (reading 'style')
          is thrown from the orphan init() callback.
-->

In a real app, the trigger is more organic: a user navigates to a page containing a <Editor>, then navigates away before the network has finished delivering tinymce.min.js. We observed this in production from users on slower devices/connections.

Suggested fix

Set a destroyed flag in onDestroy and short-circuit the queued init callback if set. Ideally also splice the listener out of state.listeners to avoid unbounded growth in long-lived SPAs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions