Skip to content

Race condition in CollaborationPlugin: Editor fails to sync when rapidly unmounted/remounted due to stale Yjs document references #7722

@tobiasandersen

Description

@tobiasandersen

The CollaborationPlugin fails to sync content from Yjs to the editor when the component is rapidly unmounted and remounted. The editor appears empty despite the document content being correctly received from the server and stored in the Yjs document. The reason this happens is that the yjsDocMap is stored globally in the CollaborationContext, and captured too early in the component's life cycle.

Here's what happens:

  1. New component instance starts mounting while old instance still exists
  2. New component initializes doc state with existing document from yjsDocMap.get(id):
    https://github.com/facebook/lexical/blob/main/packages/lexical-react/src/LexicalCollaborationPlugin.tsx#L103
  3. Old component cleanup runs, calling docMap.delete(id)
  4. New providerFactory creates a fresh Yjs document and stores it in the map
  5. New binding is created using the stale document reference from step 2
  6. Server data arrives in the new document, but the binding's observer is attached to the old document
  7. onYjsTreeChanges never fires because observer is on wrong document

Reproduction Steps

  1. Mount a component with CollaborationPlugin
  2. Quickly unmount and remount the component (e.g., rapid navigation)
  3. Observe that the editor remains empty despite server content being available

Expected Behavior

Editor should display the synced content from the Yjs document

Actual Behavior

Editor appears empty because the binding observer is attached to a stale document reference

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