One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

One Native

How One's native APIs are organized, where each runs, and how they get into your app

One ships native iOS and Android APIs inside the one package: shared views that render a native control on each platform, SwiftUI and UIKit views for iOS, Jetpack Compose views for Android, and services such as notifications, storage, and the camera. Installing one brings all of it, and the native build links it with no extra packages.

Every API hangs off the One namespace, and the namespace tells you where it runs. Reach for One.UI and the root services first; they work on both platforms. Use One.iOS or One.Android when you want a platform’s own control exactly as that platform defines it.

Usage

import { useState } from 'react'
import { One } from 'one'
function AirplaneMode() {
const [on, setOn] = useState(false)
if (One.platform === 'ios') {
return <One.iOS.Toggle label="Airplane mode" isOn={on} onIsOnChange={setOn} />
}
if (One.platform === 'android') {
return <One.Android.Switch isOn={on} onIsOnChange={setOn} />
}
return null
}

Each platform gets its own control, with that platform’s prop names, and the check keeps each one off the platform that cannot draw it.

How it works

Namespaces. The One object groups everything by where it runs:

Hooks and state helpers, such as useSizeClass and useNativeState, are named imports from one.

Platform checks. One.platform is 'ios', 'android', or 'web'. The native build sets it for each bundle it makes, and anything else reads as web. Use it, or Platform.OS, to pick between platform views.

Bridges. Services are Nitro hybrid objects: a TypeScript spec declares the interface, and Nitro generates the Swift and Kotlin bindings, so calls reach native code through JSI. Views are Fabric components: their specs declare the props and events, and React Native codegen builds the native view managers. Swift views render SwiftUI inside a hosting view; Android views render Compose inside a Compose view.

Linking. one includes a podspec, an Android Gradle module, and a codegen config, so React Native autolinking adds the native code to the Xcode and Android projects that one prebuild generates.

App config. Capabilities that change the native project, such as push, picture in picture, or the Android maps key, are set under native.app in your one() Vite config. Prebuild writes them into the plist, manifest, and Gradle files, so a change takes a new prebuild and a native build. Each page lists the keys it needs.

Platform differences

iOSAndroidWeb
One.UINative controlNative controlWeb version or nothing
One.iOSSwiftUI or UIKitThrowsThrows
One.AndroidThrowsComposeThrows
ServicesNativeNativeBrowser API or empty

Limits and gotchas

Examples

Copy with a confirmation tap

import { Pressable, Text } from 'react-native'
import { One } from 'one'
function CopyCode({ code }: { code: string }) {
async function copy() {
await One.Clipboard.setString(code)
One.Haptics.notification('success')
}
return (
<Pressable onPress={copy} accessibilityRole="button">
<Text>Copy {code}</Text>
</Pressable>
)
}

Root services need no platform check. Clipboard writes on every platform, and haptics accepts the call on web and does nothing, since browsers have no matching feedback.

Switch layouts by size class

import { Text, View } from 'react-native'
import { useSizeClass } from 'one'
function Inbox() {
const sizeClass = useSizeClass()
return (
<View style={{ flex: 1, flexDirection: sizeClass.horizontal === 'regular' ? 'row' : 'column' }}>
<Text>Folders</Text>
<Text>Messages</Text>
</View>
)
}

useSizeClass is a named import, not part of One. A regular width, such as an iPad in landscape, puts the panes side by side.

Credit

One native services use Nitro Modules, created by Marc Rousavy and Margelo. Views are Fabric components, not Nitro views.

Edit this page on GitHub.