This is beta documentation for Stream Chat React Native SDK v9. For the latest stable version, see the latest version (v8) .

Custom Attachments

How to build a custom attachment

Attachments are a property on the message object:

const messageObject = {
  id: "12312jh3b1jh2b312",
  text: "This is my test message!",
  attachments: [
    {
      type: "image",
      thumb_url: "",
    },
    {
      type: "file",
      asset_url: "",
    },
  ],
};

Attachment rendering depends on message.attachments[index].type. Built-in views:

Best Practices

  • Keep custom attachment type values unique and stable so renderers stay deterministic.
  • Pass custom attachment renderers via Channel props to avoid forking the message list.
  • Include enough metadata on the attachment object to render without extra network calls.
  • Fall back to the default UnsupportedAttachment renderer for unknown types to avoid blank messages.
  • Validate attachment payloads before sending to prevent malformed renders for other clients.

Gallery

Giphy

URLPreview

URLPreviewCompact

GalleryGiphyUrlPreviewURLPreviewCompact

FileAttachment

AudioAttachment

VideoThumbnail

UnsupportedAttachment

FileAttachmentAudioAttachmentVideoThumbnailUnsupportedAttachment

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>;