Prompt
Build a Pokemon store with a cart. Requirements:
- Show list of Pokemon with name and price
- Cart floating button showing item count
- Max 3 items per cart
- Show total price on cart button
- Cap cart total at $10
Solution
This mini-project is about enforcing business invariants at the single mutation point. "Max 3 items" and "cap at $10" are checked inside addToCart, before setCart fires — so every Add button in the app goes through the same gate and the cart cannot enter an invalid state. Guards that live in the UI ("disable the button when...") are presentation; guards that live in the mutator are correctness. You usually want both, but only one of them is load-bearing.
The other deliberate choice: total is derived, computed with reduce from the cart array at render time, not tracked as its own useState. Two states describing one fact will eventually disagree — someone adds a remove path and forgets to subtract. One state, one reduce, zero drift. If the derivation ever got expensive, the fix is useMemo, still not a second state.
The floating cart button is the standard RN overlay pattern: position: 'absolute' with bottom/right offsets inside a flex: 1 container, conditionally rendered with cart.length > 0 && so an empty cart shows nothing.
Red flag: validating the limits in the button's onPress in one screen, then adding a second entry point (deep link, "buy again") that calls setCart directly. Invariants scattered across callers are invariants you no longer have.
Say it: "The cart's rules live in the mutator, not the buttons — and the total is a reduce over the cart, because two states for one fact always drift."