# Back button/navigation between steps functions correctly

- **Pattern:** `ab-001100` (`ecommerce-cart-ux.checkout-flow.step-navigation`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001100
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001100)

## Why it matters

Shoppers fix mistakes by going back. If the back button is missing from the payment step, a shopper who notices a wrong shipping address has to abandon and start over. Worse, if back navigation clears form data, every mistake forces re-entry of twenty-plus fields. Both behaviors drive abandonment on an otherwise-committed buyer. The underlying bug is almost always state being scoped to the step component instead of the checkout container.

## Severity rationale

Medium because the defect blocks error recovery on committed buyers, not on every shopper, but data loss is severe when it hits.

## Remediation

Hoist checkout state into a parent container at `src/components/CheckoutFlow.tsx` or a React Context so step transitions read and write the same object. Render a Back button on every step except the first, and verify backward navigation does not clear `formData`.

```tsx
const [formData, setFormData] = useState({ shipping: {}, payment: {} })
const goBack = () => setStep(getPreviousStep(step))
<button onClick={goBack} disabled={step === 'shipping'}>Back</button>
```

## Detection

- **ID:** `step-navigation`
- **Severity:** `medium`
- **What to look for:** For each checkout step after the first, count whether a back/previous button or navigation link exists. Check that step transition handlers preserve form data — look for shared state (context, parent state, URL params) that survives step changes. Enumerate each step transition pair (e.g., Step 2 → Step 1, Step 3 → Step 2) and verify data is not reset. Quote the state management pattern used (e.g., `useState` in parent, React Context, URL search params).
- **Pass criteria:** At least 1 back navigation mechanism (button, link, or clickable progress step) exists on every checkout step after the first. Form data persists when navigating backward — no more than 0 fields should clear on back navigation. Report: "X of Y non-first steps have back navigation. State managed via Z."
- **Fail criteria:** Back button is missing from at least 1 non-first step, or clicking back clears previously entered form data.
- **Skip (N/A) when:** Checkout is single-step (no back navigation needed).
- **Detail on fail:** Example: `"Back button missing from Step 3 (payment). 2 of 3 non-first steps have back navigation. Shipping address data resets when navigating backward from Step 2 to Step 1."`
- **Cross-reference:** For the step count threshold, see the step-count check above. For browser back button behavior (History API), the Error Resilience audit covers navigation state management.
- **Remediation:** Implement shared step state in your checkout container at `src/app/checkout/page.tsx` or `src/components/CheckoutFlow.tsx`:

  ```tsx
  // src/components/CheckoutFlow.tsx
  function Checkout() {
    const [step, setStep] = useState('shipping')
    const [formData, setFormData] = useState({
      shipping: {},
      payment: {},
    })

    const goBack = () => {
      setStep(getPreviousStep(step))
      // Data preserved in formData state — not reset
    }

    const goForward = () => {
      if (validateStep(step, formData[step])) {
        setStep(getNextStep(step))
      }
    }

    return (
      <>
        <button onClick={goBack} disabled={step === 'shipping'}>
          Back
        </button>
        <button onClick={goForward}>
          Next
        </button>
      </>
    )
  }
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001100
