sonner-native for React Native toast interfaces
An opinionated toast component for React Native. A port of @emilkowalski's sonner.
At a glance
- What is it?
- sonner-native is a TypeScript toast package for React Native, modeled on Sonner's API and intended for Expo and native mobile applications. It supports promise states, custom content, dismissal, positioning, and dark mode, but it depends on six React Native packages and is not recommended for web applications.
- Who is it for?
- Adopt sonner-native when a React Native or Expo application wants Sonner-style transient notifications and accepts its Reanimated, gesture and native peer dependency cost. Do not choose it as the default web toast implementation or assume its README's 60 FPS statement covers every device and workload.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why sonner-native targets mobile feedback rather than browser alerts
sonner-native solves the problem of presenting short, transient feedback in React Native interfaces. Typical events include confirming that a button was pressed, reporting an error, showing progress while an asynchronous operation runs, or offering a callback from a notification. The package is aimed at developers building iOS and Android applications with React Native, especially projects already using Expo. Its source is TypeScript, and the package metadata points to `src/index.tsx` as the source entry.
The project describes itself as opinionated and as a port of `@emilkowalski's sonner`. Its README says the API fully matches Sonner's, which is useful for developers familiar with the original library, although the packages are not interchangeable everywhere. The documented variants include `success`, `error`, `warning`, `custom` and `promise`. A toast can carry a title, description, icon or action button, and can appear at the top, bottom or center.
This is a presentation component, not a general notification queue or a replacement for application navigation. It gives an application a consistent visual vocabulary for messages that appear over the current screen. The target user is therefore a React Native developer who wants rapid notification UI without designing a separate overlay, animation and dismissal system for each application.
How Toaster and toast calls fit into a React Native application
The documented integration has two parts. An application mounts a `Toaster` component near its root, while individual components call the exported `toast` function when an event occurs. The root placement matters because the README explicitly recommends putting `Toaster` in the Expo Router root layout so notifications remain visible across screens.
For a conventional React Native entry point, the documented shape places `Toaster` beside `NavigationContainer` inside a `View`. With Expo Router, it follows `Stack` and is wrapped within `GestureHandlerRootView`. The project also states that it can work outside React components, although the README excerpt does not document the precise call path or setup requirements for that usage.
The visible data flow is therefore straightforward at the public API level: an event handler calls `toast(...)`; the application-level `Toaster` provides the rendered toast host. The promise variant adds a loading state and supports changing the displayed state after an asynchronous operation. Custom JSX is available through the `custom` variant. Dismissal can occur through a swipe gesture or through `toast.dismiss()`, either for one toast or for all toasts.
The feature list says animations and interaction use Reanimated 3. That dependency makes dismissal and appearance behavior more involved than a plain text overlay, while Gesture Handler supplies the gesture side. Safe Area Context, SVG, Screens and Worklets are also listed as peer dependencies, so the component sits inside the native application stack rather than operating as an isolated view.
Installing sonner-native and mounting its first toast
The README gives an Expo-oriented installation command. Run it from the React Native project that will consume the package. The README documents this command:
npx expo install sonner-nativeThat command installs the package only. The README also says that React Native Reanimated, React Native Gesture Handler, React Native Safe Area Context, React Native SVG, React Native Screens and React Native Worklets must be installed as peer dependencies. It links to each dependency's documentation but does not provide a complete `npx expo install` command containing all six packages, so their versions should be selected through the official setup instructions for the application's React Native or Expo version.
Next, add the root host to `App.tsx` or the application entry point. The following is the README's documented pattern, with the existing navigation expression kept as shown:
import { Toaster } from 'sonner-native';
function App() {
return (
<View>
<NavigationContainer>...</NavigationContainer>
<Toaster />
</View>
);
}After mounting `Toaster`, an event handler can create a first toast. The import comes from `sonner-native`, and the button callback invokes `toast`:
import { toast } from 'sonner-native';
function SomeComponent() {
return (
<Button
title="Show Toast"
onPress={() => toast('Hello, World!')}
/>
);
}Pressing the documented button should produce a `Hello, World!` toast in the application. The README does not provide an expected screenshot or automated assertion for this first interaction, so the visible result described by the API is the toast itself.
Expo Router placement across tabs and unmatched routes
Applications using Expo Router need root-level placement rather than a `Toaster` inside one tab screen. The README directs developers to `app/_layout.tsx` and supplies a layout that includes `GestureHandlerRootView`, `Stack`, two screen declarations and `Toaster`. This is a more specific integration than the conventional `App.tsx` example.
Use the following layout as the documented starting point:
import { Toaster } from 'sonner-native';
import { Stack } from 'expo-router';
import { GestureHandlerRootView } from "react-native-gesture-handler";
export default function RootLayout() {
return (
<GestureHandlerRootView>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
<Toaster />
</GestureHandlerRootView>
);
}The stated purpose is to keep toasts visible across all screens. That is a meaningful constraint for route-based applications. Mounting the host inside a screen could scope it to that screen's lifetime, but the excerpt does not specify the exact resulting behavior, so the documented root placement is the safer choice.
The quoted import style for `GestureHandlerRootView` is part of the README example and is preserved here. Projects with a different route structure can adapt the surrounding `Stack`, but they should retain an application-level toast host and account for the gesture handler root. The README does not document a separate initialization procedure for the listed native peers beyond pointing to their own documentation.
Promise, custom and dismissable toast behavior
The `promise` variant is the most operationally relevant feature for network requests and other asynchronous work. According to the README, it includes a loading state, allowing a screen to show an in-progress message and then update it when the underlying promise resolves or fails. The excerpt does not include the exact promise invocation syntax, so an adoption decision should be based on the linked project documentation rather than an invented example.
The `custom` variant accepts custom JSX. That gives developers more control over internal layout than the standard string, title and description representation. It also shifts responsibility to the caller for keeping custom content compatible with the available toast area and dismissal behavior. The feature list separately supports custom icons and an action button with a callback, which covers common cases without requiring custom JSX.
Dismissal has several documented controls. Users can optionally swipe to dismiss, with the swipe direction configurable as left or up. Code can call `toast.dismiss()` to remove one toast, or dismiss all toasts. This flexibility is useful when a screen must coordinate feedback with a state transition, but it also means application code needs a clear policy for stale notifications. The README does not document timers, queue limits, retry behavior or what happens when a toast is dismissed before a promise settles.
Position can be top, bottom or center. That is a simple visual choice with potentially different consequences for screen content and accessibility. The excerpt does not provide overlap handling or platform-specific placement rules. Those details need verification in the advanced documentation before relying on a toast for information that users must not miss.
sonner-native versus Sonner on the web
The most direct alternative named by the project is the original Sonner. sonner-native is a port for React Native, while the README says Sonner Native works on the web but is not recommended there. The recommended approach is conditional exports that select the browser package on web and retain `sonner-native` for native platforms.
The documented split creates a small indirection layer:
// sonner.ts
export * from 'sonner-native';The platform-specific file then exports the browser implementation:
// sonner.web.ts
export * from 'sonner';The application imports from that local module rather than directly from `sonner-native`. This preserves the React Native package for native builds while using Sonner for web.
The difference is therefore platform-specific rather than cosmetic. `sonner-native` relies on React Native modules such as Reanimated, Gesture Handler, Safe Area Context, SVG, Screens and Worklets. The original Sonner is the README's recommended web package. A React Native application with substantial web support should treat this as a two-package architecture, and should verify how the chosen bundler resolves the platform suffix in that project.
Dependency, release and licensing implications
The repository is not archived, and its last push was on 2026-09-07. The listed releases include `v0.27.0` on 2026-08-15, `v0.26.5` on 2026-08-13 and `v0.26.4` on 2026-06-29. The package metadata identifies version `0.27.0`, which means consumers should check release notes and compatibility notes when moving between minor versions rather than assuming that a toast component has no behavioral changes.
The MIT license permits use and modification under that license's conditions. This review does not interpret the license or provide legal advice. The practical upgrade cost is more relevant here: every consumer must keep the peer dependency stack compatible with the React Native or Expo project. The README calls out Reanimated 3 and lists six peer dependencies, so an upgrade can involve native package configuration rather than only changing a JavaScript version.
The repository includes `CHANGELOG.md`, `SECURITY.md`, `CONTRIBUTING.md`, configuration files, `src`, `docs` and an `example` application. The package scripts include `pnpm --filter sonner-native-example`, `test`, `typecheck`, `lint` and `release`, although the excerpt does not document the result of running them. The repository therefore offers concrete places to inspect changes, but it does not state a formal support policy for older React Native or Expo versions. Verify those compatibility boundaries before adoption.
Editorial conclusion
Adopt sonner-native when a React Native or Expo application wants Sonner-style transient notifications and accepts its Reanimated, gesture and native peer dependency cost. Do not choose it as the default web toast implementation or assume its README's 60 FPS statement covers every device and workload. Verify the current peer dependency setup, required provider placement in `app/_layout.tsx`, promise lifecycle behavior and target-platform appearance before standardizing on v0.27.0.
Frequently asked questions
How do I install sonner-native in an Expo project?
The README documents `npx expo install sonner-native`. It also says that React Native Reanimated, Gesture Handler, Safe Area Context, SVG, Screens and Worklets are peer dependencies that must also be installed using their respective setup documentation.
Where should I add the sonner-native Toaster component?
For Expo Router applications, the README says to place `Toaster` in the root layout file `app/_layout.tsx` so toasts appear across screens. For a conventional application entry point, it shows `<Toaster />` alongside the navigation container inside a `View`.
Does sonner-native support web applications?
The README says that it works on the web but does not recommend using it there. It recommends exporting `sonner-native` from `sonner.ts` and exporting `sonner` from `sonner.web.ts`, then importing the platform-specific local module.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gunnartorfis-sonner-native-toasts)Was this useful?