This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 57).
useNativeState
一个 React Hook,用于创建可在 JavaScript 与原生 SwiftUI 视图之间共享的可观察状态。
useNativeState 返回一个 ObservableState,它在原生端映射到 SwiftUI 的 ObservableObject,因此对 .value 的读取和写入会被 SwiftUI 直接观察到,而不会经过 React 的渲染周期。这使你可以在 UI 线程上的 worklet 中同步更新原生视图。
安装
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Note: Using worklets requires installing
react-native-workletsin your project.useNativeStateitself works without it, but the synchronous UI-thread updates shown below depend on the worklet runtime.
The following example masks a phone number as the user types. Both the formatting and the writes to maskedPhone.value (text) and selection.value (cursor position) happen synchronously on the UI thread, so there is no flicker between the raw input and the masked value.
import { Host, TextField, useNativeState } from '@expo/ui/swift-ui'; import { keyboardType } from '@expo/ui/swift-ui/modifiers'; import { useCallback } from 'react'; export default function WorkletPhoneMaskExample() { const maskedPhone = useNativeState(''); const selection = useNativeState({ start: 0, end: 0 }); const handleTextChange = useCallback( (v: string) => { 'worklet'; const digits = v.replace(/\D/g, '').slice(0, 10); let formatted: string; if (digits.length === 0) { formatted = ''; } else if (digits.length <= 3) { formatted = digits; } else if (digits.length <= 6) { formatted = `(${digits.slice(0, 3)}) ${digits.slice(3)}`; } else { formatted = `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`; } if (formatted !== v) { maskedPhone.value = formatted; // The demo jumps straight to the end. Real masking needs smarter cursor handling. selection.value = { start: formatted.length, end: formatted.length }; } }, [maskedPhone, selection] ); return ( <Host matchContents> <TextField text={maskedPhone} selection={selection} placeholder="(555) 123-4567" modifiers={[keyboardType('phone-pad')]} onTextChange={handleTextChange} /> </Host> ); }
API
import { useNativeState } from '@expo/ui/swift-ui';
Hooks
| Parameter | Type |
|---|---|
| initialValue | T |
Creates an observable native state that is automatically cleaned up when the
component unmounts. initialValue is captured once on the first render
ObservableState<T>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 |