Skip to content

Latest commit

Β 

History

History
486 lines (370 loc) Β· 16.5 KB

File metadata and controls

486 lines (370 loc) Β· 16.5 KB

Stream Chat React Integration Guide for AI Assistants

This guide helps AI assistants provide accurate integration instructions when users ask to "integrate stream-chat-react" or similar vague commands.

Quick Start Integration Pattern

When a user wants to integrate stream-chat-react, follow this standard pattern:

1. Installation

npm install stream-chat stream-chat-react
# or
yarn add stream-chat stream-chat-react

2. Get Your Credentials

Before setting up the chat client, you'll need:

  • API Key: Get your API key from the Stream Dashboard
  • User Token: For development purposes, you can generate a user token manually using the Token Generator
    • Note: Manual token generation is for development/testing only. For production, generate tokens server-side using your Stream API secret.

3. Basic Setup (Minimal Working Example)

The minimal integration requires:

  • Stream Chat client setup
  • Chat component wrapper
  • Channel component with basic UI
import { Chat, useCreateChatClient } from 'stream-chat-react';
import 'stream-chat-react/dist/css/v2/index.css';

// Get your API key from: https://dashboard.getstream.io/
// For development, generate a token at: https://getstream.io/chat/docs/php/tokens_and_authentication/#manually-generating-tokens
const apiKey = 'YOUR_API_KEY';
const userId = 'YOUR_USER_ID';
const userName = 'YOUR_USER_NAME';
const userToken = 'YOUR_USER_TOKEN';

const App = () => {
  const client = useCreateChatClient({
    apiKey,
    tokenOrProvider: userToken,
    userData: { id: userId, name: userName },
  });

  if (!client) return <div>Setting up client & connection...</div>;

  return <Chat client={client}>Chat with client is ready!</Chat>;
};

4. Complete Chat UI Setup

For a full-featured chat interface:

import type { ChannelFilters, ChannelOptions, ChannelSort, User } from 'stream-chat';
import {
  Chat,
  Channel,
  ChannelHeader,
  ChannelList,
  MessageInput,
  MessageList,
  Thread,
  Window,
  useCreateChatClient,
} from 'stream-chat-react';
import 'stream-chat-react/dist/css/v2/index.css';

// Get your API key from: https://dashboard.getstream.io/
// For development, generate a token at: https://getstream.io/chat/docs/php/tokens_and_authentication/#manually-generating-tokens
const apiKey = 'YOUR_API_KEY';
const userId = 'YOUR_USER_ID';
const userName = 'YOUR_USER_NAME';
const userToken = 'YOUR_USER_TOKEN';

const user: User = {
  id: userId,
  name: userName,
  image: `https://getstream.io/random_png/?name=${userName}`,
};

const sort: ChannelSort = { last_message_at: -1 };
const filters: ChannelFilters = {
  type: 'messaging',
  members: { $in: [userId] },
};
const options: ChannelOptions = {
  limit: 10,
};

const App = () => {
  const client = useCreateChatClient({
    apiKey,
    tokenOrProvider: userToken,
    userData: user,
  });

  if (!client) return <div>Setting up client & connection...</div>;

  return (
    <Chat client={client}>
      <ChannelList filters={filters} sort={sort} options={options} />
      <Channel>
        <Window>
          <ChannelHeader />
          <MessageList />
          <MessageInput />
        </Window>
        <Thread />
      </Channel>
    </Chat>
  );
};

Common Integration Scenarios

Scenario 1: New React App (Vite/CRA)

User intent: "Add stream-chat-react to my React app"

Steps:

  1. Install packages: npm install stream-chat stream-chat-react
  2. Get credentials:
  3. Import CSS: import 'stream-chat-react/dist/css/v2/index.css'
  4. Set up client using useCreateChatClient hook
  5. Wrap app with <Chat> component
  6. Add <Channel> with <Window>, <MessageList>, <MessageInput>

Reference: See examples/tutorial/ for step-by-step examples

Scenario 2: Add Chat to Existing App

User intent: "Integrate chat into my existing React application"

Steps:

  1. Install packages
  2. Get credentials:
  3. Import CSS (preferably in a CSS layer for proper override precedence)
  4. Create a separate chat component or route
  5. Initialize client once at app level (use useCreateChatClient only once)
  6. Access client elsewhere using useChatContext() hook

Important: The client should be created once and reused. Don't create multiple clients.

Scenario 3: Custom Styling

User intent: "Customize the chat appearance"

Steps:

  1. Import Stream CSS into a CSS layer
  2. Create custom theme using CSS variables
  3. Apply theme via theme prop on <Chat> component
@layer base, theme;
@import 'stream-chat-react/dist/css/v2/index.css' layer(base);

@layer theme {
  .str-chat__theme-custom {
    --str-chat__primary-color: #009688;
    --str-chat__surface-color: #f5f5f5;
    /* ... more variables */
  }
}
<Chat client={client} theme='str-chat__theme-custom'>
  {/* ... */}
</Chat>

Reference: See theming documentation and examples/vite/src/stream-imports-theme.scss

Scenario 4: Custom Components

User intent: "Customize message or channel preview appearance"

Steps:

  1. Create custom component matching the prop interface
  2. Pass custom component via props (e.g., Message, ChannelPreview, Attachment)
  3. Use hooks like useMessageContext() to access data
const CustomMessage = () => {
  const { message } = useMessageContext();
  return (
    <div>
      {message.user?.name}: {message.text}
    </div>
  );
};

<Channel Message={CustomMessage}>{/* ... */}</Channel>;

Reference: See examples/tutorial/src/4-custom-ui-components/

Scenario 5: Livestream Chat

User intent: "Create a livestream-style chat"

Steps:

  1. Use livestream channel type (disables typing indicators, read receipts)
  2. Use VirtualizedMessageList instead of MessageList for performance
  3. Apply dark theme: theme="str-chat__theme-dark"
  4. Set live prop on ChannelHeader
<Chat client={client} theme='str-chat__theme-dark'>
  <Channel channel={channel}>
    <Window>
      <ChannelHeader live />
      <VirtualizedMessageList />
      <MessageInput focus />
    </Window>
  </Channel>
</Chat>

Reference: See examples/tutorial/src/7-livestream/

Scenario 6: Emoji Support

User intent: "Add emoji picker and autocomplete"

Emoji support is built into the SDK β€” the StreamEmojiPicker needs no emoji-mart packages or init() call.

Deprecation: the EmojiPicker export from stream-chat-react/emojis is the legacy emoji-mart-backed picker. It still works unchanged for backwards compatibility, but is deprecated and will be removed in v15 and logs a one-time console warning. New integrations should use StreamEmojiPicker; existing emoji-mart integrations keep working until you migrate (see Migrating from emoji-mart below).

Steps:

  1. Import StreamEmojiPicker from stream-chat-react/emojis and pass it to Channel.
  2. Import the emoji picker's stylesheet: import 'stream-chat-react/css/emoji-picker.css'. It is intentionally not part of index.css (so apps that don't use the picker ship no emoji CSS); without it the picker panel renders unstyled.
  3. (Optional) For :shortcode autocomplete + emoticon replacement, register the emoji middleware on the message composer's text composer with createTextComposerEmojiMiddleware() (no argument β€” it uses the built-in index).
import { StreamEmojiPicker } from 'stream-chat-react/emojis';
import 'stream-chat-react/css/emoji-picker.css';

<Channel EmojiPicker={StreamEmojiPicker}>{/* ... */}</Channel>;

Notes:

  • Passing a custom emojiSearchIndex (including emoji-mart's SearchIndex) is still supported for advanced use.

  • On StreamEmojiPicker, skin tone and "frequently used" are integrator-managed props (skinTone/onSkinToneChange, frequentlyUsedEmoji/onFrequentlyUsedChange); the SDK does not persist them. See examples/vite/ for a localStorage example.

  • On StreamEmojiPicker, pickerProps accepts a curated set of emoji-mart-compatible Picker options (plus theme and style):

    • Layout: navPosition / previewPosition ('top' | 'bottom' | 'none'), searchPosition ('sticky' | 'static' | 'none'), skinTonePosition ('preview' | 'search' | 'none').
    • Grid & content: perLine (default 9), categories (filter + reorder; 'frequent' always prepends), maxFrequentRows (default 1).
    • Filtering & polish: exceptEmojis, emojiVersion, noCountryFlags, previewEmoji, noResultsEmoji, autoFocus, onClickOutside.

    Divergences from emoji-mart's defaults: autoFocus defaults to true; emojiVersion is unfiltered by default (the bundled set 15); previewEmoji / noResultsEmoji default to the SDK's placeholder / empty state; noCountryFlags is opt-in (no Windows auto-detect); categories cannot reposition 'frequent'.

    Not supported (rejected by the type; ignored with a console warning at runtime): image sets (set, getSpritesheetURL), custom emoji, data, i18n / locale, dynamicWidth, icons, categoryIcons. Sizing knobs (emojiSize, emojiButtonSize, …) are --str-chat__emoji-picker-* CSS variables, not props. Skin tone uses the first-class skinTone / defaultSkinTone props (not emoji-mart's skin). Try these live in the "Emoji Picker" settings tab of examples/vite/.

  • To let users react with any emoji (the reaction selector's + button), fill reactionOptions.extended with the full emoji set. It also gates display β€” a reaction whose type isn't in quick/extended is not rendered. Load it lazily from the emojis entry (the dataset is code-split, so this adds nothing to your initial bundle):

    import { defaultReactionOptions, type ReactionOptions } from 'stream-chat-react';
    import { loadDefaultExtendedReactionOptions } from 'stream-chat-react/emojis';
    
    const [reactionOptions, setReactionOptions] =
      useState<ReactionOptions>(defaultReactionOptions);
    useEffect(() => {
      loadDefaultExtendedReactionOptions().then((extended) =>
        setReactionOptions({ ...defaultReactionOptions, extended }),
      );
    }, []);
    
    <Channel reactionOptions={reactionOptions}>{/* ... */}</Channel>;

    For a curated subset instead, build the extended map yourself with mapEmojiMartData.

  • Migrating from emoji-mart (the deprecated EmojiPicker): swap EmojiPicker β†’ StreamEmojiPicker, then remove the emoji-mart / @emoji-mart/react / @emoji-mart/data installs and any init({ data }) call. The deprecated EmojiPicker still accepts raw emoji-mart pickerProps (e.g. set, emojiSize); StreamEmojiPicker uses the curated pickerProps above. Autocomplete (createTextComposerEmojiMiddleware) and reactions (mapEmojiMartData) are engine-agnostic and need no changes.

Reference: See examples/tutorial/src/6-emoji-picker/

TypeScript Setup

For custom properties on channels, messages, attachments, etc., create a declaration file:

// stream-chat.d.ts
import { DefaultChannelData, DefaultAttachmentData } from 'stream-chat-react';

declare module 'stream-chat' {
  interface CustomChannelData extends DefaultChannelData {
    image?: string;
    name?: string;
  }

  interface CustomAttachmentData extends DefaultAttachmentData {
    image?: string;
    name?: string;
    url?: string;
  }
}

Layout Styling

Basic layout CSS for proper component positioning:

html,
body,
#root {
  height: 100%;
}
body {
  margin: 0;
}
#root {
  display: flex;
}

.str-chat__channel-list {
  width: 30%;
}
.str-chat__channel {
  width: 100%;
}
.str-chat__thread {
  width: 45%;
}

Key Components Reference

Core Components

  • <Chat> - Root provider, wraps entire chat app
  • <Channel> - Channel context provider
  • <ChannelList> - Displays list of channels
  • <MessageList> - Displays messages in channel
  • <MessageInput> - Input for sending messages
  • <Thread> - Thread/reply view
  • <Window> - Wrapper for channel UI
  • <VirtualizedMessageList> - Virtualized message list for high volume

Utility Components

  • <ChannelHeader> - Channel header with info
  • <Attachment> - Renders message attachments

Hooks

  • useCreateChatClient() - Creates and connects client (use once per app)
  • useChatContext() - Access client instance
  • useMessageContext() - Access current message data
  • useChannelContext() - Access current channel data

Common Issues & Solutions

Issue: Client not connecting

Solution: Ensure useCreateChatClient returns a client before rendering <Chat>. Show loading state while client is null.

Issue: Styles not applying

Solution:

  • Import CSS: import 'stream-chat-react/dist/css/v2/index.css'
  • Use CSS layers for proper override precedence
  • Check CSS import order

Issue: Multiple clients created

Solution: Use useCreateChatClient only once at app root. Use useChatContext() to access client elsewhere.

Issue: TypeScript errors for custom properties

Solution: Create stream-chat.d.ts file with proper type declarations (see TypeScript Setup section).

Issue: Emoji picker not working

Solution:

  • Ensure EmojiPicker from stream-chat-react/emojis is passed to Channel (or set via ComponentContext)
  • Import the emoji picker CSS: import 'stream-chat-react/css/emoji-picker.css'
  • For :shortcode autocomplete, register createTextComposerEmojiMiddleware() on the composer's text composer

Resources

Package Information

  • Package Name: stream-chat-react
  • Peer Dependencies:
    • react: ^19.0.0 || ^18.0.0 || ^17.0.0
    • react-dom: ^19.0.0 || ^18.0.0 || ^17.0.0
    • stream-chat: ^9.27.2
  • Emoji support: built in via the stream-chat-react/emojis entry point β€” no emoji-mart packages required.

Best Practices

  1. Client Creation: Create client once at app root, reuse via context
  2. CSS Layers: Use CSS layers for proper style override precedence
  3. Loading States: Always check if client is ready before rendering chat components
  4. Type Safety: Use TypeScript declaration files for custom properties
  5. Performance: Use VirtualizedMessageList for high message volume scenarios
  6. Theming: Use CSS variables and theme classes rather than direct CSS overrides
  7. Credentials: Never hardcode credentials in production; use environment variables

Integration Checklist

When helping users integrate, ensure:

  • Packages installed (stream-chat, stream-chat-react)
  • API key obtained from Stream Dashboard
  • User token generated (for development: use Token Generator)
  • CSS imported (stream-chat-react/dist/css/v2/index.css)
  • Client created with useCreateChatClient (once, at app root)
  • Loading state handled (check if (!client))
  • <Chat> component wraps chat UI
  • At minimum: <Channel> with <Window>, <MessageList>, <MessageInput>
  • Layout CSS added if needed (for proper positioning)
  • TypeScript declarations added if using custom properties
  • Theme applied if customizing appearance
  • Credentials properly configured (API key, user token, etc.)

Note for AI Assistants: When users ask vague questions like "integrate stream-chat-react", start with the Quick Start Integration Pattern above. Ask clarifying questions about their use case (new app vs existing, styling needs, features required) to provide the most relevant scenario from Common Integration Scenarios.