export type ReminderState = {
channel_cid: string;
created_at: Date;
message: MessageResponse | null;
message_id: string;
remind_at: Date | null;
timeLeftMs: number | null;
updated_at: Date;
user: UserResponse | null;
user_id: string;
};Message Reminders
Message reminders let users set follow-up notifications for specific messages. The React SDK handles the UI and state, while the low-level JS client handles the underlying CRUD operations. For API details, see the low-level client guide. The low-level client guide
Best Practices
- Keep reminder actions in the message menu for discoverability.
- Use
useMessageReminderstate for live countdowns instead of custom timers. - Keep reminder offsets small and meaningful for your product.
- Avoid frequent UI refreshes beyond the default timer boundaries.
- Provide clear feedback when reminders are created or removed.
Message Reminder UI Interaction
Users can create, update, or delete reminders from the message actions menu. When a reminder exists, the Message UI component shows a reminder notification; removing the reminder removes the notification.
Get Message Reminder Data
The React SDK uses client.reminders to perform CRUD operations. The controller maintains reactive state: a map of message IDs to Reminder instances. Each Reminder has its own reactive state that extends the server ReminderResponse with timeLeftMs.
You can subscribe at two levels:
- Subscribe to a specific reminder’s state
import { useMessageReminder, useStateStore } from "stream-chat-react";
import type { LocalMessage, ReminderState } from "stream-chat";
const reminderStateSelector = (state: ReminderState) => ({
timeLeftMs: state.timeLeftMs,
});
const Component = ({ message }: { message: LocalMessage }) => {
// access the message reminder instance
const reminder = useMessageReminder(message.id);
const { timeLeftMs } =
useStateStore(reminder?.state, reminderStateSelector) ?? {};
};timeLeftMs updates periodically. The closer the deadline, the more frequent the updates (daily → hourly → minutely), and the reverse as you move away from the deadline.
- Subscribe to reminders pagination
Pagination is handled by RemindersPaginator. The items are ReminderResponse objects from the server, not Reminder instances.
import {
InfiniteScrollPaginator,
useChatContext,
useStateStore,
} from "stream-chat-react";
import type { PaginatorState, ReminderResponse } from "stream-chat";
import { CustomLoadingIndicator } from "../LoadingIndicator";
import { CustomReminderListingItem } from "./CustomReminderListingItem";
const reminderPaginatorStateSelector = (
state: PaginatorState<ReminderResponse>,
) => ({
isLoading: state.isLoading,
items: state.items,
});
const Component = () => {
const { client } = useChatContext();
const { items, isLoading } = useStateStore(
client.reminders.paginator.state,
reminderPaginatorStateSelector,
);
return (
<InfiniteScrollPaginator
loadNextOnScrollToBottom={client.reminders.queryNextReminders}
threshold={40}
>
{items && (
<div>
{items.map((item) => (
<CustomReminderListingItem reminder={item} key={item.message_id} />
))}
</div>
)}
{isLoading && <CustomLoadingIndicator />}
</InfiniteScrollPaginator>
);
};Message Reminder Configuration
You can configure the reminder offsets users can pick from:
const minute = 60 * 1000;
client.reminders.updateConfig({
scheduledOffsetsMs: [30 * minute, 60 * minute],
});You can also set the boundary for when the reminder notification stops refreshing elapsed time:
const day = 24 * 60 * 60 * 1000;
client.reminders.updateConfig({
stopTimerRefreshBoundaryMs: day,
});Overriding Default Message Reminder Components
You can override the reminder components in the React SDK:
import {
Channel,
ReminderNotificationProps,
useMessageReminder,
useStateStore,
} from 'stream-chat-react';
import type { LocalMessage, ReminderState } from 'stream-chat';
const reminderStateSelector = (state: ReminderState) => ({
timeLeftMs: state.timeLeftMs,
});
const CustomReminderNotification = ({ reminder }: ReminderNotificationProps) => {
const { timeLeftMs } =
useStateStore(reminder?.state, reminderStateSelector) ?? {};
return (
// ... the reminder notification UI component
);
};
const Component = () => {
return (
<Channel ReminderNotification={CustomReminderNotification}>
{/* ... */}
</Channel>
);
};