Skip to content

ccs-chat-notifications-client for React

The /react entry point of ccs-chat-notifications-client has two hooks: one owns the client, the other subscribes to an event. It needs React 18 or later.

Install the package as described on the package page. react is an optional peer dependency, so your app already provides it. Import from the sub-path:

import { useChatNotifications, useChatNotificationEvent } from '@central-code-station/ccs-chat-notifications-client/react';

useChatNotifications(options) creates a ChatNotificationsClient, connects it while enabled is true (the default) and disconnects on unmount. useChatNotificationEvent(client, event, handler) subscribes to one event type while the component is mounted.

live-updates.tsx
import { useChatNotifications, useChatNotificationEvent } from '@central-code-station/ccs-chat-notifications-client/react';
import type { ReactNode } from 'react';
import { getChatAccessToken } from './fe-guide-chat-token';
export function LiveUpdates({ signedIn, children }: { signedIn: boolean; children: ReactNode }) {
const { client, connectionState } = useChatNotifications({
chatApiUrl: 'https://chat.centralcodestation.com/api/v1',
tenantId: 'fitness',
applicationId: 'fitness-app',
getAccessToken: getChatAccessToken,
enabled: signedIn, // connects and disconnects as this flips
});
// The latest handler is used on every render, so it needs no stable identity.
useChatNotificationEvent(client, 'message.created', ({ message }) => console.log(message.body));
useChatNotificationEvent(client, 'conversation.access_revoked', ({ conversation_id }) => console.log('lost', conversation_id));
return <>{connectionState === 'error' ? <p>Live updates are paused.</p> : children}</>;
}
Hook Returns or does
useChatNotifications(options) { client, connectionState, subscribeToConversation, unsubscribeFromConversation }. The options are those of ChatNotificationsClient plus enabled.
useChatNotificationEvent(client, event, handler) Subscribes for the life of the component. The latest handler is used on every render, so it needs no stable identity.

The hook creates a new client when chatApiUrl, tenantId or applicationId changes. getAccessToken is read fresh on every reconnect, so it needs no stable identity either.

Connect once near the root and pass the client down through your own context. Every component that calls useChatNotificationEvent with that client shares the one stream. See React in depth.

live-updates-provider.tsx
import { createContext, useContext, type ReactNode } from 'react';
import { useChatNotifications } from '@central-code-station/ccs-chat-notifications-client/react';
import type { ChatNotificationsClient } from '@central-code-station/ccs-chat-notifications-client';
import { context } from './fe-guide-context';
const LiveContext = createContext<ChatNotificationsClient | null>(null);
/** Connect once, near the root, and pass the client down. */
export function LiveUpdatesProvider({ signedIn, children }: { signedIn: boolean; children: ReactNode }) {
const { client, connectionState } = useChatNotifications({ ...context, enabled: signedIn });
return (
<LiveContext.Provider value={client}>
{connectionState === 'error' && <p>Live updates are paused.</p>}
{children}
</LiveContext.Provider>
);
}
export function useLiveClient(): ChatNotificationsClient {
const client = useContext(LiveContext);
if (!client) throw new Error('Wrap your app in <LiveUpdatesProvider>');
return client;
}
  • It does not store events. connectionState is state, but messages are not. Insert them into your own list, for example with mutate from useMessages.
  • It does not replay events. Events published while the stream reopens are lost, so reload data when connectionState returns to connected.
  • It has no render-time connection. During a server render connectionState is 'disconnected', and the stream opens in an effect on the client.
  • It does not handle push. Use usePushRegistration from the push entry point.