# State Management Choices — React Native

Source: https://www.skillbyai.com/en/react-native/d-state

> Where each kind of state lives.

## Separate server, client and screen state

Most apps need less global state than they think. **Server state** (data from APIs) belongs in a cache such as TanStack Query. **Local UI state** (an open modal, form fields) belongs in `useState` or `useReducer` inside the component. **Shared client state** (signed-in user, theme, cart) can use React **Context** for values that change rarely, or a small store such as **Zustand** or **Redux Toolkit** when many components read and update it, since those let components subscribe to slices and avoid unnecessary re-renders. **Navigation state** is owned by the router; put shareable values such as a filter in route params. Persist store data with the storage options from the previous topic when it must survive restarts.

## A small Zustand cart store

Components subscribe only to the slice they use (check the docs for your version).

```typescript
import { create } from "zustand";

type Item = { id: string; name: string; qty: number };

type CartState = {
  items: Item[];
  add: (item: Omit<Item, "qty">) => void;
  clear: () => void;
};

export const useCart = create<CartState>((set) => ({
  items: [],
  add: (item) =>
    set((state) => {
      const existing = state.items.find((i) => i.id === item.id);
      return existing
        ? { items: state.items.map((i) => (i.id === item.id ? { ...i, qty: i.qty + 1 } : i)) }
        : { items: [...state.items, { ...item, qty: 1 }] };
    }),
  clear: () => set({ items: [] }),
}));

// in a component: re-renders only when the count changes
// const count = useCart((s) => s.items.length);
```

## Do not copy server data into a global store

Duplicating API responses in Redux or Zustand creates two sources of truth that drift apart. Let the query cache own server data.

**Quiz:** Where does the list of products loaded from your API best live?

- [x] In a server-state cache such as TanStack Query
- [ ] In a global variable updated by hand
- [ ] In AsyncStorage on every render
- [ ] In route params of every screen

*Answer:* In a server-state cache such as TanStack Query. Server data needs caching and refetching, not just storage.
