Skip to Content
Housr AppState Management

State Management

Overview

The app uses two state management approaches:

  • Server state: React Query (TanStack Query v5) for API data
  • Global state: React Context only — no Redux, Zustand, or other state libraries

React Query Configuration

Defined in src/providers/query-provider.tsx:

const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: __DEV__ ? 0 : 5 * 60 * 1000, // 5 min (0 in dev) gcTime: __DEV__ ? 0 : 10 * 60 * 1000, // 10 min (0 in dev) retry: 2, refetchOnWindowFocus: false, }, mutations: { retry: 1, }, }, });

In development mode, stale and cache times are set to 0 so you always see fresh data.

Context Providers

Global Contexts (src/context/)

ContextFileHookPurpose
Authauth-context.tsxuseAuth()JWT token, user object, signIn/signOut/refreshUser
Feature Flagsfeature-flag-context.tsxuseFeatureFlags()Remote feature flags from featureFlags.php
Citiescity-context.tsxuseCities()Available cities list from API, coordinate lookup
Toasttoast-context.tsxuseToast()App-wide toast notifications (success/error/warning/info)
Navigation Guardnavigation-guard-context.tsxuseNavigationGuard()Auth-gated route protection
Notificationnotification-context.tsxuseNotifications()FCM token, push permission, badge management
New-to-Featurenew-to-feature-context.tsxTracks first-time feature visits
Slideable Modalslideable-modal-context.tsxShared modal state

Feature-Specific Contexts

ContextFileHookPurpose
Explore Filtersfeatures/explore/context/explore-filters-context.tsxuseExploreFilters()Filter values, sort option, persisted to AsyncStorage
Device Cityfeatures/explore/context/device-city-context.tsxuseDeviceCity()Selected city for non-logged-in users
Explore Navigationfeatures/explore/context/explore-navigation-context.tsxExplore screen navigation state

Provider Hierarchy

Providers are nested in a specific order in src/app/_layout.tsx. See Architecture for the full tree.

Key ordering constraints:

  1. AuthProvider wraps everything (including QueryProvider) so auth state is available before queries
  2. FeatureFlagProvider comes after QueryProvider since it could use queries
  3. CitiesProvider depends on DeviceCityProvider
  4. NavigationGuardProvider depends on AuthProvider for route protection

Conventions

  • No enums: Use maps/objects instead (though ViewingStatus in src/features/viewings/types/viewingStatus.ts is a legacy exception)
  • Prefer interfaces over types for object shapes
  • Descriptive boolean names: isLoading, hasError, isUsaMode
  • Context hooks throw if used outside their provider
Last updated on