tldraw/tldraw

TickManager listener lifecycle is the root cause of the strict-mode camera-state workaround

Open

#8,892 建立於 2026年5月20日

在 GitHub 查看
 (0 留言) (0 反應) (0 負責人)TypeScript (47,037 star) (3,212 fork)batch import
good first issueimprovementsdk

描述

Problem

The "reset camera state on dispose" block in Editor.ts:411–416 papers over a deeper issue: 'tick' event listeners are added by Editor after TickManager starts, but TickManager.dispose doesn't track or remove them — they're owned by the EventEmitter superclass. On React Strict Mode double-mount, listeners may re-bind to stale closure scopes.

Where

  • packages/editor/src/lib/editor/managers/TickManager/TickManager.ts:49–55dispose only cancels RAF, doesn't unregister listeners
  • packages/editor/src/lib/editor/Editor.ts:411–416 — the workaround comment plus off('tick', ...) and _setCameraState('idle') reset
  • Multiple 'tick' listener call sites across Editor.ts

Suggested fix

Let TickManager own the listener registry: onTick(cb) returns an unsubscribe, and TickManager.dispose unregisters all of them. Demote editor.inputs.updatePointerVelocity from a privileged hard-coded call inside tick() to an ordinary frame listener registered by InputsManager. Once that's symmetric, the workaround in Editor.ts:411–416 can be removed.

Context

Surfaced during an internal modularity audit of the editor manager classes.

貢獻者指南