Hooks built for native React
Keep application state reusable across React targets, then connect it to controllers adapted for native components, events, and accessibility semantics.
- Public hooks
- 8
- DOM runtime
- None
- State mode
- Controlled or local
What React and React Native share
React Native supports React’s built-in hooks and application-defined hooks. Share data, validation, domain state, and mutations in a platform-neutral workspace package. Render that state with @santi020k/lumen-react on the web and@santi020k/lumen-react-native in the native app.
Do not import the web hook implementation into React Native. Web controllers can depend on DOM focus, ARIA attributes, browser storage, CSS, and keyboard events. Hooks with portable state semantics have native adaptations from the React Native package instead.
// packages/product-state/src/use-projects.ts
import { useCallback, useState } from 'react'
export function useProjects() {
const [selectedId, setSelectedId] = useState<string | null>(null)
const selectProject = useCallback((id: string) => setSelectedId(id), [])
return { selectProject, selectedId }
}
// Web imports @santi020k/lumen-react for rendering.
// Native imports @santi020k/lumen-react-native for rendering.
// Both apps import useProjects from the shared workspace package.// packages/product-state/src/use-projects.ts
import { useCallback, useState } from 'react'
export function useProjects() {
const [selectedId, setSelectedId] = useState<string | null>(null)
const selectProject = useCallback((id: string) => setSelectedId(id), [])
return { selectProject, selectedId }
}
// Web imports @santi020k/lumen-react for rendering.
// Native imports @santi020k/lumen-react-native for rendering.
// Both apps import useProjects from the shared workspace package.Native hook reference
The adapted controllers preserve controlled and uncontrolled state ownership while returning props shaped for native Lumen components.
| Hook | Owns | Connects to |
|---|---|---|
useDisclosure / useDialog | Controlled or uncontrolled visibility | LumenAlertDialog, LumenSheet |
useTabs | Controlled or uncontrolled selected value | LumenTabs |
useSelect | Normalized options and selected value | LumenPicker or an app-owned picker |
useLanguageToggle | Locale cycling without browser side effects | Application localization provider |
useThemeToggle | Explicit light and dark selection | LumenProvider |
useToast | Bounded notification queue and dismissal timers | LumenToast |
useLumenTheme | Current semantic native theme | Custom native composition |
useLumenNavigationBarVisibility | Scroll-responsive navigation visibility | LumenCollapsibleNavigationBar |
Disclosure and dialog state
Spread dialogProps onto an alert dialog or sheet. The controller exposesshow, close, toggle, and setOpen for application events.
import {
LumenAlertDialog,
LumenButton,
useDialog
} from '@santi020k/lumen-react-native'
export function DeleteProject() {
const dialog = useDialog()
return (
<>
<LumenButton intent="danger" onPress={dialog.show}>
Delete project
</LumenButton>
<LumenAlertDialog
{...dialog.dialogProps}
confirmLabel="Delete"
destructive
onConfirm={() => {
deleteProject()
dialog.close()
}}
title="Delete this project?"
/>
</>
)
}import {
LumenAlertDialog,
LumenButton,
useDialog
} from '@santi020k/lumen-react-native'
export function DeleteProject() {
const dialog = useDialog()
return (
<>
<LumenButton intent="danger" onPress={dialog.show}>
Delete project
</LumenButton>
<LumenAlertDialog
{...dialog.dialogProps}
confirmLabel="Delete"
destructive
onConfirm={() => {
deleteProject()
dialog.close()
}}
title="Delete this project?"
/>
</>
)
}Selection state
useTabs and useSelect keep the value app-controllable. Native components continue to own touch, accessibility, and rendering behavior.
import {
LumenTabs,
useTabs
} from '@santi020k/lumen-react-native'
const options = [
{ label: 'Overview', value: 'overview' },
{ label: 'Activity', value: 'activity' }
]
export function ProjectTabs() {
const tabs = useTabs({ defaultValue: 'overview' })
return (
<LumenTabs
{...tabs.tabsProps}
label="Project sections"
options={options}
>
<ProjectPanel value={tabs.value} />
</LumenTabs>
)
}import {
LumenTabs,
useTabs
} from '@santi020k/lumen-react-native'
const options = [
{ label: 'Overview', value: 'overview' },
{ label: 'Activity', value: 'activity' }
]
export function ProjectTabs() {
const tabs = useTabs({ defaultValue: 'overview' })
return (
<LumenTabs
{...tabs.tabsProps}
label="Project sections"
options={options}
>
<ProjectPanel value={tabs.value} />
</LumenTabs>
)
}Toast queue
The queue is local to the component that calls useToast. Lift the hook to an application provider when notifications must be created from multiple screens.
import {
LumenButton,
LumenToast,
useToast
} from '@santi020k/lumen-react-native'
export function SaveProject() {
const notifications = useToast()
return (
<>
<LumenButton
onPress={() => notifications.create({
title: 'Project saved',
variant: 'success'
})}
>
Save
</LumenButton>
{notifications.toasts.map(toast => (
<LumenToast
key={toast.id}
{...notifications.getToastProps(toast)}
/>
))}
</>
)
}import {
LumenButton,
LumenToast,
useToast
} from '@santi020k/lumen-react-native'
export function SaveProject() {
const notifications = useToast()
return (
<>
<LumenButton
onPress={() => notifications.create({
title: 'Project saved',
variant: 'success'
})}
>
Save
</LumenButton>
{notifications.toasts.map(toast => (
<LumenToast
key={toast.id}
{...notifications.getToastProps(toast)}
/>
))}
</>
)
}