Skip to content

Refactor useObservableState to use React's useSyncExternalStore #3819

@odinr

Description

@odinr

Is your feature request related to a problem? Please describe.
The current useObservableState hook in packages/utils/observable/src/react/useObservableState.ts uses manual state management with useState and useLayoutEffect to subscribe to RxJS observables. While this works, React 19 provides useSyncExternalStore (and related APIs) which is specifically designed for subscribing to external stores and provides better performance, concurrent rendering support, and automatic handling of edge cases like tearing.

Describe the solution you'd like
Refactor useObservableState to use React's useSyncExternalStore hook instead of the current manual subscription approach. This will:

  1. Leverage React's built-in support for external stores
  2. Improve performance and compatibility with concurrent rendering features
  3. Reduce the amount of custom subscription logic
  4. Align with React 19 best practices for external data sources

The refactored implementation should:

  • Maintain the same API surface and behavior
  • Support both Observable and StatefulObservable types
  • Handle initial values, errors, and completion states
  • Preserve all existing functionality including teardown callbacks
  • Update tests to ensure backward compatibility

Describe alternatives you've considered

  • Keeping the current implementation (not ideal as it doesn't leverage React 19 improvements)
  • Creating a new hook alongside the existing one (would create API duplication)

Additional context

  • Current implementation: packages/utils/observable/src/react/useObservableState.ts
  • Related test file: packages/utils/observable/tests/react/useObservableState.test.ts
  • React version: 19.2.1 (supports useSyncExternalStore)
  • The hook is used throughout the codebase (e.g., useAppSettings, useAppSetting, etc.)

References:

  • React 19 useSyncExternalStore documentation
  • Current implementation uses useObservableLayoutSubscription which could also benefit from this refactor

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions