const messageObject = {
id: "12312jh3b1jh2b312",
text: "This is my test message!",
attachments: [
{
type: "image",
thumb_url: "",
},
{
type: "file",
asset_url: "",
},
],
};Custom Attachments
How to build a custom attachment
Attachments are a property on the message object:
Attachment rendering depends on message.attachments[index].type. Built-in views:
- attachment type
audio- AudioAttachment - attachment type
video- renders a VideoThumbnail in the Gallery. - attachment type
image- Gallery (single or multiple images) - attachment type
giphy- Giphy - attachment type
file- FileAttachment - attachment with URL - URLPreview
- compact URL preview - URLPreviewCompact
Best Practices
- Keep custom attachment
typevalues unique and stable so renderers stay deterministic. - Pass custom attachment renderers via
Channelprops to avoid forking the message list. - Include enough metadata on the attachment object to render without extra network calls.
- Fall back to the default
UnsupportedAttachmentrenderer for unknown types to avoid blank messages. - Validate attachment payloads before sending to prevent malformed renders for other clients.
|
|
|
|
| Gallery | Giphy | UrlPreview | URLPreviewCompact |
|
|
|
|
| FileAttachment | AudioAttachment | VideoThumbnail | UnsupportedAttachment |
Default components handle these types in MessageList. You can override them, for example:
const CustomGiphy = ({ attachment, onPressIn }) => {
console.log(attachment.type);
console.log(attachment.actions)
console.log(attachment.image_url)
console.log(attachment.thumb_url)
console.log(attachment.title)
console.log(attachment.type)
return (/** Your custom UI */)
}
const CustomGallery = ({ images, onPressIn }) => {
console.log(images);
return (/** Your custom UI */)
}
const CustomFileAttachment = ({ attachment }) => {
console.log(attachment.mime_type);
console.log(attachment.title);
console.log(attachment.file_size);
console.log(attachment.actions);
return (/** Your custom UI */)
}
const CustomUrlPreview = () => {
console.log(text);
console.log(thumb_url);
console.log(title);
return (/** Your custom UI */)
}
// Provide these custom components to Channel, as props.
<Channel
Gallery={CustomGallery}
Giphy={CustomGiphy}
FileAttachment={CustomFileAttachment}
UrlPreview={CustomUrlPreview}
>You can also use a custom type. Custom attachments render in the Card view by default, which you can override.
const CustomCardComponent = ({ type, ...otherProperties }) => {
console.log(type);
console.log(otherProperties);
return (/** Your custom UI */)
}
<Channel Card={CustomCardComponent} />Handling Custom Properties On Attachment
Default UI components and context providers from the SDK are memoized for performance purpose, and will not trigger re-renders upon updates to custom properties on attachment.
Eg: Suppose we add a customField property to the attachment object and use it the UI in custom UnsupportedAttachment component.
<Channel
UnsupportedAttachment={(attachment) => {
return (
<View>
<Text>{attachment.customField}</Text>
</View>
);
}}
/>In this example, if you try to update customField on particular attachment from backend (or anywhere), you will not see it updated on UI until you refresh the chat.
The reason being, the default memoization logic only checks for fixed set of properties on attachment, and doesn't check for custom properties.
This can be solved by providing a function which checks for changes in custom properties which you may have been defined on attachment.
import { Channel } from "stream-chat-react-native";
const isAttachmentEqualHandler = (prevAttachment, nextAttachment) => {
const attachmentEqual =
prevAttachment.customField === nextAttachment.customField;
if (!attachmentEqual) return false;
return true;
};
<Channel
channel={channel}
isAttachmentEqual={isAttachmentEqualHandler}
UnsupportedAttachment={(attachment) => {
return (
<View>
<Text>{attachment.customField}</Text>
</View>
);
}}
>
{/* The underlying components */}
</Channel>;






