Mobile State Management

State management in mobile apps means juggling several distinct kinds of state at once: ephemeral UI state, app-wide global state, remote server data, and state that must survive app restarts. The most common architectural mistake is treating them all the same — cramming server data into a global store, or hoisting UI state higher than it needs to go.

The guiding rule: keep state as local as possible, reach for global state only when data is genuinely shared, and treat server state as its own category (with caching, refetching, and loading/error handling) rather than hand-managing it in a global store.

TL;DR

Quick Example

Local state is the default — useState (RN) / StatefulWidget (Flutter):

State Types

Use global state for: authentication, app settings/preferences, shopping cart, real-time data shared across screens, theme/locale. Most other state should stay local.

React Native Patterns

For server state, use TanStack/React Query rather than stuffing API data into Redux — you get caching, refetching, and loading/error states for free:

Flutter Patterns

Persistence

Persist only what should survive restarts (auth tokens, cart, preferences):

⚠️ Don't persist sensitive secrets in plain storage — use secure storage (Keychain/Keystore) for tokens and credentials.

Best Practices

Common Mistakes

Putting server data in a global store

Over-globalizing UI state

FAQ

What's the difference between client state and server state?

Client state is owned and mutated entirely by your app — UI toggles, form inputs, the current theme. Server state is a cache of data that actually lives on a backend — user profiles, lists, anything fetched over the network. They have different needs: server state requires caching, background refetching, staleness handling, and loading/error states, which is why dedicated tools (React Query, SWR) exist. Conflating them — managing server data in a global client store — is the most common state mistake.

Do I need Redux, or is Context enough?

Context is fine for low-frequency global state like auth, theme, or locale — values that don't change often. It's not ideal for high-frequency updates (every change rerenders all consumers) or complex state logic. Reach for Redux Toolkit (or Zustand, which is lighter) when you have substantial shared state with complex updates. For server data, neither — use React Query. Match the tool to the state's nature and update frequency.

Provider, Riverpod, or BLoC in Flutter?

Provider is simple and well-established (ChangeNotifier + notifyListeners). Riverpod is the modern evolution — type-safe, testable, decoupled from the widget tree — and a strong default for new apps. BLoC suits teams wanting strict, event-driven structure and clear separation of business logic. All work; pick one and apply it consistently. For small apps, plain setState may suffice.

What state should I persist across app restarts?

Persist state that users expect to survive: authentication tokens, cart contents, user preferences/settings, and any in-progress work you don't want them to lose. Don't persist transient UI state or server data you can refetch. Use a whitelist (redux-persist) to be deliberate, and store sensitive values (tokens, credentials) in secure storage (Keychain/Keystore), not plain AsyncStorage/SharedPreferences.

Related Topics

References