Fix cart quantities doubling on every logout/login and a crash on /cart
Root cause 1 (count doubling): LogoutButton never cleared the local cart, and mergeServerCartIntoLocal() (called on login) adds server quantities into the existing local ones rather than replacing — since CartSync mirrors local to the server continuously, local and server already held the same quantities at logout time, so every login added them together, doubling the count each cycle. Fix: clear the local cart on logout, so the next login's merge starts from empty (or only genuine guest-session additions) instead of re-adding already-synced quantities. Root cause 2 (page couldn't load): readCart()/getCart() only guarded against JSON.parse syntax errors, not against the parsed value being a non-array — once localStorage held a corrupted (inflated/malformed) value, CartContent.tsx's cart.map() threw uncaught during render. Fix: validate Array.isArray() after parsing, falling back to []. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+12
-5
@@ -18,7 +18,8 @@ function readCart(): CartItem[] {
|
||||
if (typeof window === "undefined") return [];
|
||||
try {
|
||||
const raw = window.localStorage.getItem(CART_KEY);
|
||||
return raw ? JSON.parse(raw) : [];
|
||||
const parsed = raw ? JSON.parse(raw) : [];
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
@@ -90,7 +91,8 @@ export function getCart(): CartItem[] {
|
||||
if (raw === cachedRaw) return cachedItems;
|
||||
cachedRaw = raw;
|
||||
try {
|
||||
cachedItems = raw ? JSON.parse(raw) : EMPTY_CART;
|
||||
const parsed = raw ? JSON.parse(raw) : EMPTY_CART;
|
||||
cachedItems = Array.isArray(parsed) ? parsed : EMPTY_CART;
|
||||
} catch {
|
||||
cachedItems = EMPTY_CART;
|
||||
}
|
||||
@@ -125,9 +127,14 @@ export function useCart(): CartItem[] {
|
||||
// Called right after a successful login (LoginForm.tsx, CheckoutContent.tsx's
|
||||
// inline login toggle) — folds whatever was saved server-side into the
|
||||
// local cart by quantity (addToCart adds to an existing line rather than
|
||||
// overwriting it), so items added before logging in aren't lost. CartSync
|
||||
// then picks up the resulting change and pushes the merged cart back to
|
||||
// the server on its own, closing the loop without a separate save call here.
|
||||
// overwriting it), so items added as a guest before logging in aren't lost.
|
||||
// This only stays correct because LogoutButton.tsx clears the local cart on
|
||||
// logout — the local cart is always either empty (no guest additions since
|
||||
// the last logout) or holds only genuinely new guest-session items, never a
|
||||
// stale copy of what's already in the server cart, so this add never
|
||||
// double-counts. CartSync then picks up the resulting change and pushes the
|
||||
// merged cart back to the server on its own, closing the loop without a
|
||||
// separate save call here.
|
||||
export async function mergeServerCartIntoLocal(): Promise<void> {
|
||||
try {
|
||||
const res = await fetch("/api/account/cart");
|
||||
|
||||
Reference in New Issue
Block a user