import { useCreateChatClient } from " stream-chat";
const App = () => {
const chatClient = useCreateChatClient({
apiKey,
tokenOrProvider: userToken,
userData: { id: userId },
});
useEffect(() => {
if (!chatClient) return;
chatClient.setMessageComposerSetupFunction(({ composer }) => {
composer.linkPreviewsManager.enabled = true;
});
}, [chatClient]);
};
Link Previews in Message Input
The purpose of link previews in the MessageInputis to provide visual guides of what a user may expect to be rendered later in the
MessageListby [
Card` component](/chat/docs/sdk/react/components/message-components/attachment#card/) among message attachments.
Link previews are rendered once enabled via MessageComposer
:
Rendering link previews
The link previews are rendered using LinkPreviewList
. The component subscribes to changes in MessageComposer.linkPreviewsManager
state to render the list of link previews.
The default LinkPreviewList
component lists all the successfully loaded and loading previews.
The default link preview UI is implemented for:
Message input
Edit message form
Link Preview customization
Custom rendering of link previews
If the default link previews UI does not meet our expectations, we can provide a custom component. To render our own LinkPreviewList
, we just need to pass it to Channel
prop `LinkPreviewList. The custom component should internally subscribe to changes in message composer’s link preview manager.
import {
Channel,
LinkPreviewListProps,
LinkPreviewCard,
useMessageComposer,
} from "stream-chat-react";
import { LinkPreviewsManagerState } from "stream-chat";
// on every link preview manager state extract these link previews
const linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({
linkPreviews: Array.from(state.previews.values()).filter(
(preview) =>
LinkPreviewsManager.previewIsLoaded(preview) ||
LinkPreviewsManager.previewIsLoading(preview),
),
});
const CustomLinkPreviewList = ({ linkPreviews }: LinkPreviewListProps) => {
const { linkPreviewsManager } = useMessageComposer();
// subscribe to link preview manager's state change
const { linkPreviews } = useStateStore(
linkPreviewsManager.state,
linkPreviewsManagerStateSelector,
);
const showLinkPreviews = linkPreviews.length > 0;
if (!showLinkPreviews) return null;
return (
<div className="str-chat__link-preview-list">
{linkPreviews.map((linkPreview) => (
<LinkPreviewCard
key={linkPreview.og_scrape_url}
linkPreview={linkPreview}
/>
))}
</div>
);
};
const App = () => (
<Channel LinkPreviewList={CustomLinkPreviewList}>{/* ... */}</Channel>
);
Link preview states
In the above example we can notice, that the LinkPreview
object comes with property state
. This property can be used to determine, how the preview for a given link should be rendered. These are the possible states a link preview can acquire:
enum LinkPreviewState {
/** Link preview has been dismissed using MessageInputContextValue.dismissLinkPreview **/
DISMISSED = "dismissed",
/** Link preview could not be loaded, the enrichment request has failed. **/
FAILED = "failed",
/** Link preview has been successfully loaded. **/
LOADED = "loaded",
/** The enrichment query is in progress for a given link. **/
LOADING = "loading",
/** The preview reference enrichment has not begun. Default status if not set. */
PENDING = "pending",
}
Behavior customization
The following aspect of link preview management in MessageInput
can be customized:
- The debounce interval for the URL discovery and enrichment requests.
- URL discovery
- Link preview dismissal
All is done via MessageComposer
configuration API:
import { useCreateChatClient } from "stream-chat";
import type { LinkPreview } from "stream-chat";
import { customUrlDetector } from "./urlDetection";
const App = () => {
const chatClient = useCreateChatClient({
apiKey,
tokenOrProvider: userToken,
userData: { id: userId },
});
useEffect(() => {
if (!chatClient) return;
chatClient.setMessageComposerSetupFunction(({ composer }) => {
composer.updateConfig({
linkPreviews: {
debounceURLEnrichmentMs: 2000,
enabled: true,
findURLFn: customUrlDetector,
onLinkPreviewDismissed: (linkPreview: LinkPreview) => {
chatClient.notifications.addInfo({
message: "Link prevew dismissed",
origin: { emitter: composer.linkPreviewsManager },
});
},
},
});
});
}, [chatClient]);
};