Skip to content

Commit dba80b6

Browse files
committed
feat(toast): add ToastItemRenderer component
1 parent ce01433 commit dba80b6

File tree

4 files changed

+35
-16
lines changed

4 files changed

+35
-16
lines changed

example/src/app/(home)/components/toast.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
useToast,
55
type ToastComponentProps,
66
} from 'heroui-native';
7-
import { useCallback } from 'react';
87
import { View } from 'react-native';
98
import type { UsageVariant } from '../../../components/component-presentation/types';
109
import { UsageVariantFlatList } from '../../../components/component-presentation/usage-variant-flatlist';
@@ -94,18 +93,15 @@ const MyToast = ({ id }: ToastComponentProps) => {
9493
const InteractiveDemoContent = () => {
9594
const toast = useToast();
9695

97-
const _renderToast = useCallback(
98-
({ id }: ToastComponentProps) => <MyToast id={id} />,
99-
[]
100-
);
96+
const _renderToast = ({ id }: ToastComponentProps) => <MyToast id={id} />;
10197

10298
return (
10399
<View className="flex-1 px-5">
104100
<View className="flex-1 justify-center gap-3">
105101
<Button
106102
onPress={() => {
107103
toast.show({
108-
id: 'my-toast',
104+
// id: 'my-toast',
109105
component: _renderToast,
110106
});
111107
}}

src/providers/toast/provider.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
createContext,
3-
Fragment,
43
useCallback,
54
useContext,
65
useMemo,
@@ -10,6 +9,7 @@ import {
109
import { View } from 'react-native';
1110
import { InsetsContainer } from './insets-container';
1211
import { toastReducer } from './reducer';
12+
import { ToastItemRenderer } from './toast-item-renderer';
1313
import type {
1414
ToasterContextValue,
1515
ToastId,
@@ -80,14 +80,9 @@ export function ToastProvider({ insets, children }: ToastProviderProps) {
8080
{children}
8181
<InsetsContainer insets={insets}>
8282
<View className="flex-1">
83-
{toasts.map((toastItem) => {
84-
const content =
85-
typeof toastItem.component === 'function'
86-
? toastItem.component({ id: toastItem.id })
87-
: toastItem.component;
88-
89-
return <Fragment key={toastItem.id}>{content}</Fragment>;
90-
})}
83+
{toasts.map((toastItem) => (
84+
<ToastItemRenderer key={toastItem.id} toastItem={toastItem} />
85+
))}
9186
</View>
9287
</InsetsContainer>
9388
</ToasterContext.Provider>

src/providers/toast/reducer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ export function toastReducer(
1717

1818
case 'HIDE': {
1919
// Hide specific toasts by ID
20-
return state.filter((toast) => !action.payload.ids.includes(toast.id));
20+
// Use loose equality to handle string/number ID comparisons
21+
return state.filter(
22+
(toast) =>
23+
!action.payload.ids.some((id) => String(id) === String(toast.id))
24+
);
2125
}
2226

2327
case 'HIDE_ALL':
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { memo } from 'react';
2+
import type { ToastItem } from './types';
3+
4+
/**
5+
* Memoized toast item component to prevent unnecessary re-renders
6+
* Only re-renders when the toast item itself changes
7+
*/
8+
export const ToastItemRenderer = memo(
9+
({ toastItem }: { toastItem: ToastItem }) => {
10+
const content =
11+
typeof toastItem.component === 'function'
12+
? toastItem.component({ id: toastItem.id })
13+
: toastItem.component;
14+
15+
return content;
16+
},
17+
(prevProps, nextProps) => {
18+
// Only re-render if the toast ID or component reference changed
19+
return (
20+
prevProps.toastItem.id === nextProps.toastItem.id &&
21+
prevProps.toastItem.component === nextProps.toastItem.component
22+
);
23+
}
24+
);

0 commit comments

Comments
 (0)