Skip to content

Finally fixes the stale checkout sidebar bug#148

Merged
damianlegawiec merged 2 commits into
mainfrom
fix/stale-checkout-bug
May 14, 2026
Merged

Finally fixes the stale checkout sidebar bug#148
damianlegawiec merged 2 commits into
mainfrom
fix/stale-checkout-bug

Conversation

@damianlegawiec
Copy link
Copy Markdown
Member

@damianlegawiec damianlegawiec commented May 14, 2026

When customer was leaving checkout to storefront, changing cart and going back to checkout the sidebar wasn't re-rendered

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where the checkout page could display an outdated cart after navigation; the checkout now detects cart mismatches and refreshes order data so the summary reflects current items.
  • Improvements
    • Checkout sidebar summary now updates immediately when cart contents change, ensuring accurate order totals and line items before completing purchase.

Review Change Stack

Review Change Stack

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
storefront Ready Ready Preview, Comment May 14, 2026 0:03am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

Walkthrough

CheckoutPageContent now reads shared cart state via useCart(), computes a line-item fingerprint to detect router-cache divergence, refetches the checkout order when line items differ (preserving address/country/auth state), and republishes the CheckoutSidebar whenever cart changes.

Changes

Cart Context Integration and Cart State Sync

Layer / File(s) Summary
CartContext integration entry points
src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx
Page imports useCart and retrieves contextCart from CartContext alongside existing checkout/router/auth state.
Line-item fingerprint helper
src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx
Adds cartItemsFingerprint(cart) that computes a fingerprint from line-item id:quantity pairs only.
Cart divergence detection and sync effect
src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx
A useEffect watches contextCart and, when contextCart.id matches cartId but fingerprints differ, calls getCheckoutOrder(cartId) and replaces the page cart with the fetched checkout (with cancellation guarding), leaving address/country/auth fields intact.
Sidebar publishing adjustment
src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx
useLayoutEffect for CheckoutSidebar removes prior cartKey/prevOrderKeyRef short-circuit and re-publishes the sidebar summary whenever cart changes (dependency array updated).

Sequence Diagram

sequenceDiagram
  participant CheckoutPage as CheckoutPageContent
  participant CartContext as CartContext (useCart)
  participant API as getCheckoutOrder
  participant LocalState as local cart state

  CheckoutPage->>CartContext: read contextCart
  CheckoutPage->>LocalState: compute cartItemsFingerprint(contextCart) vs fingerprint(local cart)
  alt fingerprints differ and contextCart.id == cartId
    CheckoutPage->>API: getCheckoutOrder(cartId)
    API-->>CheckoutPage: fetched checkout cart
    CheckoutPage->>LocalState: replace local cart with fetched checkout
  end
  Note right of CheckoutPage: useLayoutEffect republishes CheckoutSidebar whenever LocalState (cart) changes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • spree/storefront#147: Both PRs modify CheckoutPageContent.tsx’s sidebar useLayoutEffect by removing the cartKey/prevOrderKeyRef short-circuit and re-publishing CheckoutSidebar whenever cart changes.

Poem

🐰 In a hop and a sniff, the rabbit spies,
Line-item prints that tell no lies.
When cache drifts and items roam,
Fetch and stitch the cart back home.
Hooray — the sidebar sings, all snug in its ties. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the PR objective: it claims to fix the stale checkout sidebar bug, which is exactly what the changeset addresses through cart state synchronization and sidebar re-rendering logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/stale-checkout-bug

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx (1)

62-76: 💤 Low value

Consider sorting line items before fingerprinting for stability.

cartItemsFingerprint relies on positional order of cart.items. If the backend ever returns items in a different order across responses (e.g., after a quantity change re-orders the list), the fingerprint will differ even though the line items are set-equal, triggering a benign but unnecessary setCart(contextCart) overwrite that throws away locally accumulated totals/discount state. A small sort by id makes the comparison order-independent.

♻️ Proposed refactor
 function cartItemsFingerprint(cart: Cart | null): string {
   if (!cart) return "";
-  return (cart.items ?? []).map((i) => `${i.id}:${i.quantity}`).join(",");
+  return (cart.items ?? [])
+    .map((i) => `${i.id}:${i.quantity}`)
+    .sort()
+    .join(",");
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx
around lines 62 - 76, The cartItemsFingerprint function relies on the order of
cart.items and should be made order-independent: inside cartItemsFingerprint
(and where Cart/cart.items is used) sort the items deterministically (e.g., by
i.id) before mapping to `${i.id}:${i.quantity}` so that the fingerprint reflects
set-equivalence rather than array order; update cartItemsFingerprint to operate
on a sorted copy of cart.items to avoid mutating the original array.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx:
- Around line 280-285: The sync effect that updates local cart from CartContext
should be gated on the context loading flag to avoid applying stale line items;
extract loading from useCart (e.g., const { cart: contextCart, loading:
contextLoading } = useCart()) and update the effect in CheckoutPageContent so it
returns early when contextLoading is true (add contextLoading to the dependency
array), keeping the existing checks (contextCart truthiness, id match via
cartId, fingerprint equality via cartItemsFingerprint) and only calling
setCart(contextCart) when loading is false and fingerprints differ.

---

Nitpick comments:
In `@src/app/`[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx:
- Around line 62-76: The cartItemsFingerprint function relies on the order of
cart.items and should be made order-independent: inside cartItemsFingerprint
(and where Cart/cart.items is used) sort the items deterministically (e.g., by
i.id) before mapping to `${i.id}:${i.quantity}` so that the fingerprint reflects
set-equivalence rather than array order; update cartItemsFingerprint to operate
on a sorted copy of cart.items to avoid mutating the original array.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 876263b3-294a-47ac-8403-93ee58e86163

📥 Commits

Reviewing files that changed from the base of the PR and between 8df1529 and 3fd269a.

📒 Files selected for processing (1)
  • src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx

Comment thread src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx Outdated
When customer was leaving checkout to storefront, changing cart and going back to checkout the sidebar wasn't re-rendered
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx:
- Around line 62-76: The cartItemsFingerprint function currently builds a
fingerprint using cart.items order; to make it robust to differing orderings,
sort the items by a stable key (use i.id) before mapping to
`${i.id}:${i.quantity}` and joining; update the cartItemsFingerprint
implementation to sort (e.g., ascending by id) on (cart.items ?? []) prior to
creating the fingerprint so identical sets produce identical fingerprints
regardless of array order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e5381c82-88e0-42cb-ad03-952419191a73

📥 Commits

Reviewing files that changed from the base of the PR and between 3fd269a and f6a5b59.

📒 Files selected for processing (1)
  • src/app/[country]/[locale]/(checkout)/checkout/[id]/CheckoutPageContent.tsx

@damianlegawiec damianlegawiec merged commit e4a0dc3 into main May 14, 2026
6 checks passed
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