
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
react-native-bread
Advanced tools
A lightweight toast library for React Native with premium feeling animations and complex gesture support
An extremely lightweight, opinionated toast component for React Native.
success, error, info, promise, and customI18nManager)bun add react-native-bread
This package requires the following peer dependencies:
| Package | Version |
|---|---|
| react-native-reanimated | >= 4.1.0 |
| react-native-gesture-handler | >= 2.25.0 |
| react-native-safe-area-context | >= 5.0.0 |
| react-native-screens | >= 4.0.0 |
| react-native-svg | >= 15.8.0 |
| react-native-worklets | >= 0.5.0 |
If you don't have these installed, you can install all peer dependencies at once:
bun add react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-screens react-native-svg react-native-worklets
Or with npm:
npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-screens react-native-svg react-native-worklets
Note: Make sure your
react-native-reanimatedandreact-native-workletsversions are compatible. Reanimated 4.1.x works with worklets 0.5.x-0.7.x, while Reanimated 4.2.x requires worklets 0.7.x only.
import { BreadLoaf } from 'react-native-bread';
function App() {
return (
<View>
<NavigationContainer>...</NavigationContainer>
<BreadLoaf />
</View>
);
}
When using Expo Router, place the BreadLoaf component in your root layout file (app/_layout.tsx):
import { BreadLoaf } from 'react-native-bread';
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
<BreadLoaf />
</>
);
}
This ensures the toasts will be displayed across all screens in your app.
import { toast } from 'react-native-bread';
// Basic usage
toast.success('Saved!');
// With description
toast.success('Saved!', 'Your changes have been saved');
toast.error('Error', 'Something went wrong');
toast.info('Tip', 'Swipe to dismiss');
// Promise toast - shows loading, then success/error
toast.promise(fetchData(), {
loading: { title: 'Loading...', description: 'Please wait' },
success: { title: 'Done!', description: 'Data loaded' },
error: (err) => ({ title: 'Failed', description: err.message }),
});
// Custom toast - fully custom content with animations
toast.custom(({ dismiss }) => (
<View style={{ padding: 16, flexDirection: 'row', alignItems: 'center' }}>
<Image source={{ uri: 'avatar.png' }} style={{ width: 40, height: 40 }} />
<Text>New message from John</Text>
<Button title="Reply" onPress={dismiss} />
</View>
));
Pass an options object as the second argument to customize individual toasts:
toast.success('Saved!', {
description: 'Your changes have been saved',
duration: 5000,
icon: <CustomIcon />,
style: { backgroundColor: '#fff' },
dismissible: true,
showCloseButton: true,
deduplication: false, // Opt out of deduplication for this toast
});
Create fully custom toasts where you control all the content. Your component fills the entire toast container and receives all entry/exit/stack animations automatically:
// Using a render function (recommended - gives access to dismiss)
toast.custom(({ dismiss, id, type, isExiting }) => (
<View style={{ padding: 16, flexDirection: 'row', alignItems: 'center', gap: 12 }}>
<Image source={{ uri: 'avatar.png' }} style={{ width: 44, height: 44, borderRadius: 22 }} />
<View style={{ flex: 1 }}>
<Text style={{ fontWeight: '600' }}>New message</Text>
<Text style={{ color: '#666' }}>Hey, check this out!</Text>
</View>
<Pressable onPress={dismiss}>
<Text style={{ color: '#3b82f6' }}>Reply</Text>
</Pressable>
</View>
));
// Or pass a React component directly
toast.custom(<MyNotificationCard />);
// With options
toast.custom(<MyToast />, {
duration: 5000,
dismissible: false,
style: { backgroundColor: '#fef2f2' }
});
Customize all toasts globally via the config prop on <BreadLoaf />:
<BreadLoaf
config={{
position: 'bottom',
rtl: false, // Code-level RTL — not needed if using native RTL (I18nManager)
stacking: true,
maxStack: 3,
defaultDuration: 4000,
colors: {
success: { accent: '#22c55e', background: '#f0fdf4' },
error: { accent: '#ef4444', background: '#fef2f2' },
}
}}
/>
Available options include:
'top' | 'bottom' - Where toasts appeartrue, see below)Deduplication is enabled by default. When the same toast is shown repeatedly (e.g., rapid button taps), it prevents stacking identical toasts. Instead, it resets the timer and plays a feedback animation:
Disable globally:
<BreadLoaf config={{ deduplication: false }} />
Or per-toast (overrides global config):
// Opt out for a specific toast
toast.info('New message', { deduplication: false });
// Explicitly enable for a specific toast (redundant when global is on)
toast.success('Liked!', { deduplication: true });
By default, a toast is considered a duplicate when it matches the front toast by title, type, and description. For stable matching across different content, provide an id — the existing toast's content will be updated:
toast.success('Saved item 1', { deduplication: true, id: 'save-action' });
toast.success('Saved item 2', { deduplication: true, id: 'save-action' }); // updates content, resets timer
| Method | Description |
|---|---|
toast.success(title, description?) | Show success toast |
toast.error(title, description?) | Show error toast |
toast.info(title, description?) | Show info toast |
toast.promise(promise, messages) | Show loading → success/error toast |
toast.custom(content, options?) | Show fully custom toast with your own content |
toast.dismiss(id) | Dismiss a specific toast |
toast.dismissAll() | Dismiss all toasts |
Toasts automatically appear above native modals on iOS.
On Android, you have two options:
The simplest fix is to use containedModal presentation instead of modal. On Android, modal and containedModal look nearly identical, so this is an easy swap:
<Stack.Screen
name="(modal)"
options={{ presentation: Platform.OS === "android" ? "containedModal" : "modal" }}
/>
This renders the modal within the React hierarchy on Android, so toasts from your root <BreadLoaf /> remain visible.
If you need native modals, add <ToastPortal /> inside your modal layouts:
// app/(modal)/_layout.tsx
import { Stack } from "expo-router";
import { ToastPortal } from "react-native-bread";
export default function ModalLayout() {
return (
<>
<Stack screenOptions={{ headerShown: false }} />
<ToastPortal />
</>
);
}
The ToastPortal component only renders on Android - it returns null on iOS, so no platform check is needed.
FAQs
A lightweight toast library for React Native with premium feeling animations and complex gesture support
We found that react-native-bread demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.