Master state management patterns. Learn to persist data across messages and handle complex user interactions.
Try the app, view the code, or explore the components.
By the end of this lesson, you will:
ChatGPT Apps need to maintain state across multiple messages. In this module, we explore patterns for managing state effectively.
Each tool call is stateless by default. But users expect:
Store temporary state in the widget using React state or localStorage.
// In your widget
const [cart, setCart] = useState(() => {
return JSON.parse(localStorage.getItem('cart') || '[]');
});
Use for: Shopping carts, form progress, UI preferences
Store state on your server, keyed by user/session ID.
# In your MCP server
user_state = redis.get(f"user:{user_id}:state")
Use for: User data, persistent preferences, history
Pass state through the conversation itself.
Use for: Multi-step workflows, confirmations
Our FPL app demonstrates all three patterns:
| State Type | Example | Storage |
|---|---|---|
| Session | Selected players for comparison | localStorage |
| Server | User's team, watchlist | Database |
| Context | "Compare those two players" | Conversation |
User: "Show me Salah's stats"
↓
Tool: get_player_stats(player_id)
↓
Returns: Player data + "player-detail" widget
↓
Widget: Renders stats, adds "Compare" button
↓
User clicks "Compare" → stores player in session
↓
User: "Compare with Saka"
↓
Tool: compare_players(player_ids)
↓
Widget: Side-by-side comparison