Skip to main content

Migrate Select from Polaris React

Replace Polaris React Select with s-select and explicit s-option children. Keep the selected value in form or app state, and preserve the stable values that backend operations expect.

If the app renders this controlled field through React, upgrade to React 19 first. React 18 doesn't provide the custom-element property and event behavior this example relies on. If you can't upgrade yet, leave the controlled Polaris React field in place during this migration slice.


Anchor to Migrate a select fieldMigrate a select field

The destination moves the options descriptor array into child elements and keeps validation on the field.

Migrating a required shipping-origin field

<s-select
label="Shipping origin"
error="Select your primary shipping location to calculate accurate rates for customers"
required
value=""
>
<s-option value="">Select a country</s-option>
<s-option value="ca">Canada</s-option>
<s-option value="us">United States</s-option>
<s-option value="mx">Mexico</s-option>
<s-option value="uk">United Kingdom</s-option>
</s-select>
import {Select} from '@shopify/polaris';

export function ShippingOrigin({
selectedOrigin = '',
validationError = 'Select your primary shipping location to calculate accurate rates for customers',
onChange,
}) {
return (
<Select
label="Shipping origin"
requiredIndicator
value={selectedOrigin}
error={validationError}
onChange={onChange}
options={[
{label: 'Select a country', value: ''},
{label: 'Canada', value: 'ca'},
{label: 'United States', value: 'us'},
{label: 'Mexico', value: 'mx'},
{label: 'United Kingdom', value: 'uk'},
]}
/>
);
}

Preview


Anchor to Replace option descriptorsReplace option descriptors

Polaris ReactPolaris web componentsMigration notes
optionsExplicit s-option childrenMove label to child text and keep value.
Option groups-option-group with s-option childrenKeep meaningful group labels rather than flattening a long list.
Option disableddisabled on s-optionPreserve unavailable choices without changing their values.
labellabelKeep a visible field label unless nearby context makes it redundant.
labelHiddenlabelAccessibilityVisibility="exclusive"Keep an accessible label.
helpTextdetailsKeep supporting instructions with the field.
placeholderplaceholderUse it as a prompt, not as a substitute for the label.
requiredIndicatorrequiredThe property adds semantics and an indicator. Set error when validation fails.
valuevaluePass the controlled selected value.
onChange(selected, id)onChange(event)Read event.currentTarget.value.
errorerrorPass a specific recovery message as a string.
disableddisabledPreserve the condition that controls availability.

Use the same option values before and after migration unless the backend contract is changing deliberately. Changing a display label shouldn't change the serialized value.


Anchor to Choose the right choice controlChoose the right choice control

Use s-select for one compact choice from a list. Use s-choice-list when merchants benefit from seeing every option or when choices need individual descriptions. Don't use a select for actions such as Create, Delete, or Export.

For a controlled select, update app state from the change event and pass that value back to the component. For a native form submission, keep a unique name and verify that the submitted value matches the backend input.


  • Choose every enabled option and verify its stable value reaches app state and form submission.
  • Test placeholders, required validation, and field-level errors.
  • Verify disabled fields and disabled options can't be selected.
  • Test long and localized labels at narrow widths.
  • Reload editing forms and confirm the current value restores correctly.

Anchor to Remove Polaris ReactRemove Polaris React

After every call site is migrated, remove Select, descriptor-only option builders, and callback adapters. Remove @shopify/polaris only after no other route in scope imports it.



Was this page helpful?