This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
TextField
A SwiftUI TextField component for text input.
Expo UI TextField matches the official SwiftUI TextField API and supports single-line and multiline input, keyboard configuration, submit handling, and an imperative ref for programmatic control.
Installation
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Basic text field
import { useState } from 'react'; import { Host, TextField } from '@expo/ui/swift-ui'; export default function BasicTextFieldExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField placeholder="Username" onValueChange={setValue} /> </Host> ); }
Multiline text field
Set axis="vertical" to allow the text field to expand vertically. Use the lineLimit modifier to control the visible line count. When using Host matchContents, add fixedSize({ horizontal: false, vertical: true }) so the text field accepts the parent's width while using its ideal height.
import { useState } from 'react'; import { Host, TextField } from '@expo/ui/swift-ui'; import { lineLimit, fixedSize } from '@expo/ui/swift-ui/modifiers'; export default function MultilineTextFieldExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField axis="vertical" placeholder="Tell us about yourself..." onValueChange={setValue} modifiers={[lineLimit(5), fixedSize({ horizontal: false, vertical: true })]} /> </Host> ); }
Keyboard type
Use the keyboardType modifier to display a specific keyboard layout.
import { useState } from 'react'; import { Host, TextField } from '@expo/ui/swift-ui'; import { keyboardType, autocorrectionDisabled } from '@expo/ui/swift-ui/modifiers'; export default function KeyboardTypeExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField placeholder="Email" onValueChange={setValue} modifiers={[keyboardType('email-address'), autocorrectionDisabled()]} /> </Host> ); }
Submit handling
Use the submitLabel modifier to customize the return key and onSubmit to handle the submit action.
import { useState } from 'react'; import { Host, TextField } from '@expo/ui/swift-ui'; import { submitLabel, onSubmit } from '@expo/ui/swift-ui/modifiers'; export default function SubmitHandlingExample() { const [value, setValue] = useState(''); return ( <Host matchContents> <TextField placeholder="Search..." onValueChange={setValue} modifiers={[submitLabel('search'), onSubmit(() => console.log('Submitted:', value))]} /> </Host> ); }
Imperative ref
Use a ref to imperatively set text, focus, blur, or select text.
import { useRef } from 'react'; import { Host, TextField, TextFieldRef, Button, HStack, VStack } from '@expo/ui/swift-ui'; import { buttonStyle } from '@expo/ui/swift-ui/modifiers'; export default function ImperativeRefExample() { const ref = useRef<TextFieldRef>(null); return ( <Host matchContents> <VStack> <TextField ref={ref} defaultValue="Select me!" placeholder="Imperative field" /> <HStack spacing={12}> <Button modifiers={[buttonStyle('bordered')]} onPress={() => ref.current?.focus()} label="Focus" /> <Button modifiers={[buttonStyle('bordered')]} onPress={() => ref.current?.blur()} label="Blur" /> <Button modifiers={[buttonStyle('bordered')]} onPress={() => ref.current?.setText('SwiftUI rocks!')} label="Set Text" /> <Button modifiers={[buttonStyle('bordered')]} onPress={() => ref.current?.setSelection(0, 7)} label="Select" /> </HStack> </VStack> </Host> ); }
API
import { TextField } from '@expo/ui/swift-ui';
Component
Type: React.Element<TextFieldProps>
Renders a SwiftUI TextField.
boolean • Default: falseIf true, the text field will be focused automatically when mounted.
string • Default: 'horizontal'The axis along which the text field grows when content exceeds a single line.
'horizontal'— single line (default).'vertical'— expands vertically for multiline content. UselineLimitmodifier to cap visible lines.
Acceptable values are: 'vertical' | 'horizontal'
ReactNodeSlot children — supports <TextField.Placeholder> with a <Text> child
(any text-styling modifiers on that Text are preserved as the
placeholder's styling).
numberMaximum number of characters allowed. Truncates natively as the user types.
(focused: boolean) => voidA callback triggered when the field gains or loses focus.
(selection: {
end: number,
start: number
}) => voidA callback triggered when the text selection range changes.
(text: string) => voidA callback triggered when the text value changes.
If the callback is marked with the 'worklet' directive, it runs synchronously
on the UI thread; otherwise it is delivered asynchronously as a regular JS event.
Ref<TextFieldRef>ObservableState<TextFieldSelection>Observable state the field writes the current selection to.
Create with useNativeState<TextFieldSelection>({ start: 0, end: 0 }).
Use ref.setSelection(start, end) to set programmatically.
ObservableState<string>An observable state that holds the current text.
Create one with useNativeState('') or useNativeState('initial value').
If omitted, the field manages its own internal state.
Types
Observable state shared between JavaScript and native views (Jetpack Compose on Android and SwiftUI on iOS).
Type: SharedObject extended by:
| Property | Type | Description |
|---|---|---|
| onChange | [listener] | null | A single listener invoked on the native UI runtime whenever the value changes
(after iOS The callback must be a worklet so it can run synchronously on the UI thread.
Attach it inside Example
|
| value | T | The current value. Writes from a UI worklet are synchronous and immediately readable. Writes from the JS thread are scheduled to the UI thread asynchronously, the new value is not readable until the update has been applied. Prefer writing from a worklet when you need synchronous updates |
| get | () => T | Reads the current value. A React Compiler compliant alternative to reading |
| set | (value: T) => void | Writes a new value. A React Compiler-compliant alternative to assigning |
Can be used for imperatively focusing and setting text/selection on the TextField component.