---
title: Migrate TextField from Polaris React
description: >-
  Replace Polaris React TextField with the Polaris web component field that
  matches the value and input behavior.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/text-field
  md: >-
    https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/text-field.md
api_name: app-home
---

# Migrate Text​Field from Polaris React

Polaris React `TextField` covered several input types and multiline values. Replace each call site with the most specific Polaris web component field so browsers, password managers, mobile keyboards, validation, and form submission understand the value.

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

***

## Choose the destination field

| Existing value | Polaris web components |
| - | - |
| General single-line text | [`s-text-field`](https://shopify.dev/docs/api/app-home/web-components/forms/text-field) |
| Email address | [`s-email-field`](https://shopify.dev/docs/api/app-home/web-components/forms/email-field) |
| Number | [`s-number-field`](https://shopify.dev/docs/api/app-home/web-components/forms/number-field) |
| Password or secret | [`s-password-field`](https://shopify.dev/docs/api/app-home/web-components/forms/password-field) |
| URL | [`s-url-field`](https://shopify.dev/docs/api/app-home/web-components/forms/url-field) |
| Search query | [`s-search-field`](https://shopify.dev/docs/api/app-home/web-components/forms/search-field) |
| Multiline text | [`s-text-area`](https://shopify.dev/docs/api/app-home/web-components/forms/text-area) |

Don't route every call site to `s-text-field`. For example, changing a numeric field into a general text field loses numeric input behavior and makes range validation harder to maintain.

***

## Migrate a field and validation

## Migrating a validated text field

##### Polaris web components

```html
<s-text-field
  label="SKU"
  value="TSHIRT-001"
  autocomplete="off"
  error="SKU 'TSHIRT-001' already exists. SKUs must be unique across all products."
></s-text-field>
```

##### Polaris React

```tsx
import {TextField} from '@shopify/polaris';

export function ProductSku({
  sku = 'TSHIRT-001',
  error = "SKU 'TSHIRT-001' already exists. SKUs must be unique across all products.",
  onChange,
}) {
  return (
    <TextField
      label="SKU"
      value={sku}
      error={error}
      autoComplete="off"
      onChange={onChange}
    />
  );
}
```

***

## Map shared field properties

| Polaris React | Polaris web components | Migration notes |
| - | - | - |
| `label` | `label` | Keep a concise, persistent label. |
| `labelHidden` | `labelAccessibilityVisibility="exclusive"` | Don't remove the accessible name. |
| `helpText` | `details` | Keep format or usage guidance with the field. |
| `error` | `error` | Pass a specific string that explains how to recover. |
| `requiredIndicator` | `required` | The property doesn't create an error automatically. Validate and set `error` when needed. |
| `value` | `value` | Pass the controlled string value. |
| `onChange(value, id)` | `onInput(event)` or `onChange(event)` | Use `onInput` for immediate state updates and read `event.currentTarget.value`. Use `onChange` when commit-style timing fits the workflow. |
| `autoComplete` | `autocomplete` | Keep a valid autocomplete token for the field's purpose. |
| `placeholder` | `placeholder` | Use examples or format hints, not the only label. |
| `disabled` and `readOnly` | `disabled` and `readOnly` | Preserve whether the value is unavailable or view-only. |
| `maxLength` | `maxLength` | Keep client and server limits aligned. |
| `multiline` | `s-text-area` and `rows` | Choose a text area and an appropriate initial height. |
| `type="number"`, `min`, `max`, and `step` | `s-number-field`, `min`, `max`, and `step` | Keep the value numeric in domain and validation code. |

Review prefix, suffix, connected controls, clear buttons, and vertical content individually. Don't rebuild unsupported adornments around every field. Keep units in a clear label or adjacent semantic text, and put separate actions outside the field when they remain understandable and keyboard reachable.

***

## Preserve validation and submission

Use one source of truth for the displayed value, client validation, and submission payload. Server validation remains authoritative. After a failed submission, restore the attempted values and show each field error next to its control, plus page-level feedback when the whole submission failed.

Set a stable `name` when using native form submission. Verify empty values, whitespace normalization, locale-specific number input, and secret redaction rather than assuming the old `TextField` adapters still run.

***

## Test the migration

* Enter, clear, paste, autofill, and submit every field type.
* Verify immediate and commit-style event timing doesn't duplicate requests.
* Trigger required, format, range, uniqueness, and server validation errors.
* Test browser autofill and the intended mobile keyboard for email, number, URL, and search fields.
* Reload editing forms and verify controlled values don't reset unexpectedly.
* Confirm labels, details, errors, prefixes, and units are announced in the intended order.

***

## Remove Polaris React

After every call site is migrated, remove `TextField`, value-only callback adapters, and adornment wrappers that no longer have a caller. Remove `@shopify/polaris` only after no other route in scope imports it.

***

## Related guidance

* [Polaris web component forms](https://shopify.dev/docs/api/app-home/web-components)
* [Migrate Form from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/form)
* [Migrate InlineError from Polaris React](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react/inline-error)

***
