Skip to content

fix(router): remove setInitialState override pattern from SPA navigation#223

Merged
mohamedmansour merged 1 commit intomainfrom
fix/remove-ability-to-set-initial-state
Apr 13, 2026
Merged

fix(router): remove setInitialState override pattern from SPA navigation#223
mohamedmansour merged 1 commit intomainfrom
fix/remove-ability-to-set-initial-state

Conversation

@mohamedmansour
Copy link
Copy Markdown
Contributor

The router previously checked for a user-defined setInitialState method on route components and fell back to applyStateAsAttributes when absent. This created two problems:

  1. App developers were overriding setInitialState to manually assign @observable and @attr properties — duplicating what the framework base class already does automatically. Every override was a potential source of bugs (missed properties, wrong types, stale state).

  2. Route params (e.g. :folderId, :threadId) were passed as a second argument to setInitialState, mixing concerns. Params are HTML attributes that @attr reflects; state is JSON that @observable consumes. These are two different mechanisms.

Changes:

  • Router now always calls the framework's built-in setInitialState(state) which sets @observable properties and synchronously flushes DOM updates via (). No override needed or supported.

  • Route params are set as HTML attributes (kebab-case) before setInitialState, so @attr reflection handles them automatically. E.g. params.threadId becomes attribute thread-id on the element.

  • Removed applyStateAsAttributes fallback — the framework's setInitialState + \ handles all cases: scalars via @observable setters, arrays/objects via complex property bindings with synchronous child flush.

  • Moved isInitialNavigation flag before async work to prevent a race condition where a user click during SSR bootstrap component loading could re-enter the initial navigation path.

The router previously checked for a user-defined setInitialState method on
route components and fell back to applyStateAsAttributes when absent.
This created two problems:

1. App developers were overriding setInitialState to manually assign
   @observable and @attr properties — duplicating what the framework
   base class already does automatically. Every override was a potential
   source of bugs (missed properties, wrong types, stale state).

2. Route params (e.g. :folderId, :threadId) were passed as a second
   argument to setInitialState, mixing concerns. Params are HTML
   attributes that @attr reflects; state is JSON that @observable
   consumes. These are two different mechanisms.

Changes:

- Router now always calls the framework's built-in setInitialState(state)
  which sets @observable properties and synchronously flushes DOM updates
  via \(). No override needed or supported.

- Route params are set as HTML attributes (kebab-case) before
  setInitialState, so @attr reflection handles them automatically.
  E.g. params.threadId becomes attribute thread-id on the element.

- Removed applyStateAsAttributes fallback — the framework's
  setInitialState + \ handles all cases: scalars via
  @observable setters, arrays/objects via complex property bindings
  with synchronous child flush.

- Moved isInitialNavigation flag before async work to prevent a race
  condition where a user click during SSR bootstrap component loading
  could re-enter the initial navigation path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mohamedmansour mohamedmansour merged commit 092a3e4 into main Apr 13, 2026
28 of 29 checks passed
@mohamedmansour mohamedmansour deleted the fix/remove-ability-to-set-initial-state branch April 13, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants