applyAttributeChange is undoing UI selections

Topic summary

A developer encountered an issue where using applyAttributeChange in a Shopify Checkout Extension caused UI inputs (Select/Radio) to immediately revert to their unselected state after user interaction.

Root Cause:
Shopify’s Form UI components are controlled components, requiring state management outside the component itself to function properly.

Solution:
Implement React’s useState and setState hooks to manage component state externally. The value property must be bound to the component’s state, and change handlers should update both the local state and apply attribute changes.

Key Implementation:

  • Use useState to create state variables for each form input
  • Bind the input’s value property to the state variable
  • In change handlers, update state via setState before calling applyAttributeChange
  • This ensures the UI reflects user selections while properly updating checkout attributes

The issue was resolved by following React’s controlled component pattern as documented in both Shopify and React documentation.

Summarized with AI on November 10. AI used: claude-sonnet-4-5-20250929.

I’m building a Checkout Extension to include some Questions as part of the checkout flow. When the user answers the question I need to add the value to the CheckoutAttributes for use post checkout.

The normal event handlers work fine but as soon as I include the applyAttributeChange , every time the event handler is called the UI input (Select or Radio) reverts back to the unselected state instantly. What am I doing wrong?

import React, { useState, useEffect } from 'react';
import {
  BlockStack,
  BlockSpacer,
  Choice,
  Heading,
  Select, 
  Text,
  reactExtension,
  useApplyAttributeChange
} from '@shopify/ui-extensions-react/checkout';
import { ChoiceList, InlineStack } from '@shopify/ui-extensions/checkout';

export default reactExtension(
  'purchase.checkout.contact.render-after',
  () =>

I found the answer to this. In the Shopify docs it mentions that the Form UI components are controlled components, https://shopify.dev/docs/api/checkout-ui-extensions/2024-04/components/forms/select which means the state needs to be saved outside of the component in order to access and work with it.

This React document helps explain how to solve the issue https://legacy.reactjs.org/docs/forms.html#controlled-components

The new code ends up looking like this using the ‘useState’ and ‘setState’

function Extension() {
  const applyAttributeChange = useApplyAttributeChange();
  const [primaryActivity, setPrimaryActivity] = useState('');
  const [firstPurchase, setFirstPurchase] = useState('')

  function changeFirstPurchase(value){
    setFirstPurchase(value);

    const result = applyAttributeChange({
      key: 'firstPurchase',
      type: 'updateAttribute',
      value: firstPurchase,
    });
  }

  function onPrimaryActivityChange(value){
    setPrimaryActivity(value);

    const result = applyAttributeChange({
      key: 'primaryActivity',
      type: 'updateAttribute',
      value: value,
    });
  }

and for the component the value needs to be bound to the class’s state property