Skip to content

Make signal dependency reads explicit with track() #134

Description

@kostyafarber

Problem

We hit a stale computed bug where selection bounds kept showing the previous rectangle because the bounds computed called a snapshot-style helper that used peek() internally. The computed did not subscribe to selection.stateCell, so it only refreshed when some unrelated dependency caused it to rerun.

This is easy to miss when a computed uses helpers that hide whether they read reactive values or snapshots.

Direction

Prefer explicit invalidation reads when a computed/effect needs a signal only as a dependency:

computed(() => {
  track(editor.selection.stateCell);
  return editor.selectionBounds();
});

Use .value only when the value is actually consumed in that scope. If the value is not consumed, use track(cell) so the dependency is visually obvious.

Tasks

  • Audit computed/effect/render props code for .value reads whose value is not directly used.
  • Replace invalidation-only .value reads with track(cell).
  • Check computed helpers that call snapshot APIs (peek(), snapshot getters, imperative helpers) and add explicit track(...) at the computed boundary.
  • Consider adding an oxlint rule that flags unused .value reads and suggests track(cell).

Acceptance criteria

  • Invalidation-only signal dependencies use track(cell).
  • Computeds that rely on snapshot-style helpers explicitly track their source cells.
  • The selection-bounds stale-rect class of bug is covered by either a regression test or lintable pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions