Skip to Content
Engineering11 Documentation 🔥
FrontendCapabilitiesState Management

State Management

Each platform provides opinionated state management patterns out of the box — you inherit proven approaches instead of debating architecture.

Per-Platform Patterns

PlatformPrimary PatternServer StateReactive Primitives
FlutterSafeValueNotifier + StoresFirestore streamsValueListenableBuilder, SelectValueListenableBuilder
Angular@ngrx/component-storeFirestore servicesthis.select(), this.effect(), this.updater()
React (Web)TanStack Query + ContextTanStack QueryuseQuery, useMutation, useInfiniteQuery
React NativeTanStack Query + ContextTanStack QuerySame as web (shared packages)

Flutter

The Foundation provides SafeValueNotifier — a disposal-safe extension of Flutter’s ValueNotifier that silently drops updates and listener registrations after dispose():

class SafeValueNotifier<T> extends ValueNotifier<T> { bool isDisposed = false; @override set value(T newValue) { if (isDisposed) return; super.value = newValue; } }

State is organized in layers:

LayerRoleExample
StoresDomain state holders — manage data and expose it via SafeValueNotifierConversationStore, JobTemplateStore
ControllersScreen-level orchestrators — combine stores and services for UI coordinationSaveAsTemplateController
SDK instancesFeature state — initialized via Sdk.initialize() and resolved from DIAuthSdk, MessagingSdk

SelectValueListenableBuilder only rebuilds when a specific slice of state changes:

SelectValueListenableBuilder( valueListenable: _value, selector: (v) => v.currentTheme, builder: (context, currentTheme, child) { return E11ThemeProvider(data: currentTheme, child: widget.child); }, )

Migration note: The codebase is transitioning from GetX observables (.obs, Rx, Obx) to SafeValueNotifier + ValueListenableBuilder. New code uses value notifiers exclusively; existing GetX usage is refactored on touch.

Angular

SDK libraries exclusively use @ngrx/component-store — a lightweight, component-scoped reactive state container:

@Injectable({ providedIn: 'root' }) export class CommunityStore extends ComponentStore<CommunityState> { readonly communities$ = this.select(state => state.communities); readonly loadCommunities = this.effect<void>(trigger$ => trigger$.pipe( switchMap(() => this.communityService.getAll().pipe( tapResponse( communities => this.updateCommunities(communities), error => this.handleError(error), ), )), ), ); readonly updateCommunities = this.updater( (state, communities: Community[]) => ({ ...state, communities }), ); }

Every SDK provides its own ComponentStore. Product apps inherit the pattern and use EntityAdapter for collection management.

React / React Native

Server state is managed via TanStack Query with custom hooks wrapping the IRepository abstraction:

// Firestore document query (provided by Foundation) const { data, isLoading } = useDocumentQuery<UserModel>( userRepository, userId, ); // Firestore collection with realtime updates const { data: messages } = useCollectionQuery<Message>( messageRepository, { where: [['conversationId', '==', id]] }, { subscribe: true }, ); // Infinite scroll const { data, fetchNextPage } = useCollectionInfiniteQuery<Job>( jobRepository, { orderBy: ['createdAt', 'desc'], limit: 20 }, );

The Foundation provides mutation hooks for add, update, delete, set, transaction, and batch operations — all with automatic cache invalidation.

State TypeSolution
Server / asyncTanStack Query (queries, mutations, infinite scroll, realtime subscriptions)
AuthPlatform auth context + Firebase auth state listeners
ThemeCSS variables + ThemeProvider (web), E11ThemeProvider context (mobile)
URLnuqs for search params (web)
ServicesDI container via useContainer()

What You Get

  • Pre-configured state management per platform — no architecture debates
  • SDK stores for every Foundation domain (auth, messaging, notifications, files, etc.)
  • Reactive data layer with caching, invalidation, and realtime support
  • Selector patterns that minimize unnecessary re-renders/rebuilds

What You Build on Top

  • Product-specific stores/queries for domain data
  • Screen-level controllers or hooks that compose Foundation stores
  • Custom selectors for product-specific state slices

Next Steps

  • Architecture — How state management fits the layered architecture
  • Platforms — Platform-specific details
Last updated on