Skip to content

Audit and simplify base-node-viewer effects #628

Description

@malibio

Overview

Audit all $effect blocks in base-node-viewer.svelte and refactor or eliminate them by using $derived, event handlers, or onMount/onDestroy patterns.

Problem Statement

base-node-viewer.svelte started with 8+ $effect blocks, making data flow difficult to understand. The goal was to eliminate unnecessary effects by adopting idiomatic Svelte 5 patterns.

Original effects (audited and addressed):

  1. View context and children loading when nodeId changes → Moved to onMount
  2. $effect.pre for content save watching → LEGITIMATE (retained)
  3. Node deletion detection effect → LEGITIMATE (retained)
  4. Structural watcher for sibling ordering → LEGITIMATE (retained)
  5. Placeholder creation/clearing effect → Converted to $derived
  6. Multiple async loading effects → Consolidated into onMount pattern
  7. Component lazy loading → Moved to onMount with synchronous resolution

Solution Implemented

Reduced from 8+ effects to 3 legitimate $effect blocks that represent necessary reactive side effects:

  1. Content save watcher (line 437): Monitors content changes for persistence coordination
  2. Node deletion detector (line 515): Tracks structural changes for cleanup
  3. Structural watcher (line 626): Maintains parent-child relationship integrity

These remaining effects are documented as legitimate because they represent true reactive side effects that cannot be expressed as derived state or moved to event handlers without breaking reactivity.

Acceptance Criteria

  • Each effect in base-node-viewer audited and categorized
  • Effects that should be $derived converted (viewerPlaceholder)
  • Effects that should be lifecycle hooks moved to onMount/onDestroy
  • Reduced to 3 legitimate $effect blocks (down from 8+, all necessary)
  • All viewer functionality preserved
  • Navigation, scroll position, lazy loading all work
  • Code passes bun run quality:fix
  • Tests pass (bun run test:all)

Completed Work

✅ Converted to Better Patterns:

  • ✅ Converted viewerPlaceholder from $state to $derived.by with lazy ID getter
  • ✅ Converted async loading effect to onMount pattern (eliminated infinite loop)
  • ✅ Implemented lifecycle hooks (onMount/onDestroy) for initialization
  • ✅ Synchronous component resolution (pre-load in onMount)
  • ✅ Fixed Svelte 5 runtime mutation error (plain variable for placeholderId)
  • ✅ Created comprehensive placeholder pattern documentation
  • ✅ Optimized performance with batch loading and debouncing

✅ Legitimate Effects Retained (Documented):

  • Line 437: $effect.pre for content save watcher - monitors reactive changes
  • Line 515: $effect for node deletion detection - cleanup coordination
  • Line 626: $effect.pre for structural watcher - relationship integrity

Technical Specifications

File Modified

  • base-node-viewer.svelte: packages/desktop-app/src/lib/design/components/base-node-viewer.svelte

Related Issues

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions