Skip to content

refactor: replace React Context with Zustand for state management#32

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1776433887-zustand-state-refactor
Open

refactor: replace React Context with Zustand for state management#32
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1776433887-zustand-state-refactor

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented Apr 17, 2026

Summary

Replaces the buggy React Context-based state management in context/StateContext.js with a Zustand store (v4.5.7, compatible with React 17). Fixes four known bugs, adds cart persistence via localStorage, and wraps the app in an error boundary.

Bug fixes:

  • Typo: toggleCartItemQuanititytoggleCartItemQuantity (in store, Cart.jsx destructuring, and onClick handlers)
  • Mutation: onAdd no longer mutates the product prop directly (product.quantity = quantity); instead creates a new object via spread
  • Map missing return: .map() in onAdd now returns cartProduct for non-matching items (previously returned undefined)
  • Desync: totalPrice and totalQuantities are now derived from cartItems on every read instead of tracked as separate state

New features:

  • Cart items persist to localStorage via zustand/middleware persist (keyed as cart-storage, only cartItems are persisted)
  • clearCart action replaces the manual localStorage.clear() + three separate setter calls on the success page
  • ErrorBoundary class component wraps the entire app in _app.js

Backward compatibility: StateContext component is kept as a pass-through wrapper (<>{children}</>) so _app.js doesn't need structural changes beyond adding the ErrorBoundary.

Review & Testing Checklist for Human

  • Verify cart add/remove/quantity flows in browser — the core store logic was fully rewritten; npm run build passes but no runtime UI testing was performed. Add items, increment/decrement quantities, remove items, and confirm totals update correctly.
  • Verify cart persistence — add items to cart, refresh the page, confirm items are restored. Then complete a checkout (success page) and confirm the cart is cleared from localStorage (cart-storage key).
  • Check SSR hydration — Zustand persist hydrates on the client. Confirm product pages (SSG) don't flash stale/empty cart state on initial load (check for hydration mismatches in console).
  • localStorage.clear() behavior change in success.js — the old code cleared ALL localStorage; the new code only resets the Zustand store (which updates the cart-storage key). Confirm this is acceptable and no other localStorage keys depended on being cleared here.
  • ErrorBoundary fallback styling — the fallback UI uses className="error-boundary" but no CSS was added (per ticket constraint of no styling changes). Verify the unstyled fallback is acceptable or if a follow-up is needed.

Suggested test plan: Run npm run dev, add multiple products to the cart, adjust quantities up/down, remove an item, verify the subtotal is correct, refresh the page to confirm persistence, then click "Pay with Stripe" or navigate to /success to verify the cart clears.

Notes

  • Zustand v4 was chosen over v5 because v5 requires useSyncExternalStore from React 18, and this project runs React 17.
  • The useStateContext() hook subscribes to the full store (no granular selectors), matching the previous Context re-render behavior. Performance optimization with selectors can be a follow-up.
  • showCart and qty are intentionally not persisted — cart drawer should be closed and quantity selector should reset on page refresh.

Link to Devin session: https://app.devin.ai/sessions/d85ed244776d42ac81f8e2e663f26032
Requested by: @Colhodm


Open with Devin

- Replace context/StateContext.js with Zustand store (zustand v4)
- Fix typo: toggleCartItemQuanitity -> toggleCartItemQuantity
- Fix mutation bug: no longer mutates product.quantity prop directly
- Fix map bug: .map() now returns cartProduct for non-matching items
- Fix desync bug: totalPrice and totalQuantities are derived from cartItems
- Add cart persistence via zustand/middleware persist with localStorage
- Add clearCart action for success page
- Update Cart.jsx to use fixed toggleCartItemQuantity name
- Update success.js to use clearCart instead of manual state reset
- Add ErrorBoundary component wrapping the app in _app.js
- Keep backward-compatible StateContext wrapper and useStateContext hook

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant