Support reactions in your app built with XMTP
Use the reaction content type to support reactions in your app. A reaction is a quick and often emoji-based way to respond to a message. Reactions are usually limited to a predefined set of emojis or symbols provided by the messaging app.
You're welcome to provide feedback by commenting on the Proposal for emoji reactions content type XIP idea.
Configure the content type
In some SDKs, the ReactionCodec
is already included in the SDK. If not, you can install the package using the following command:
- JavaScript
- React
- Kotlin
- Swift
- Dart
- React Native
In the JavaScript SDK, you need to import this package first.
npm i @xmtp/content-type-reaction
After importing the package, you can register the codec.
import {
ContentTypeReaction,
ReactionCodec,
} from "@xmtp/content-type-reaction";
// Create the XMTP client
const xmtp = await Client.create(signer, { env: "dev" });
xmtp.registerCodec(new ReactionCodec());
The React SDK supports all current standards-track content types, but only text messages are enabled out of the box. Adding support for other standards-track content types requires a bit of configuration.
import {
XMTPProvider,
reactionContentTypeConfig,
} from "@xmtp/react-sdk";
const contentTypeConfigs = [
reactionContentTypeConfig,
];
createRoot(document.getElementById("root") as HTMLElement).render(
<StrictMode>
<XMTPProvider contentTypeConfigs={contentTypeConfigs}>
<App />
</XMTPProvider>
</StrictMode>,
);
import org.xmtp.android.library.codecs.ReactionCodec
Client.register(codec = ReactionCodec())
Client.register(ReactionCodec());
import 'package:xmtp/src/content/reaction_codec.dart';
import 'package:xmtp/src/content/codec_registry.dart';
var registry = CodecRegistry()..registerCodec(ReactionCodec());
const client = await Client.create(signer, {
env: "production",
codecs: [new ReactionCodec()],
});
Create a reaction
With XMTP, reactions are represented as objects with the following keys:
reference
: ID of the message being reacted toaction
: Action of the reaction (added or removed)content
: String representation of the reaction (smile, for example) to be interpreted by clientsschema
: Schema of the reaction (Unicode, shortcode, or custom)
- JavaScript
- React
- Kotlin
- Swift
- Dart
- React Native
const reaction = {
reference: someMessageID,
action: "added",
content: "smile",
};
await conversation.send(reaction, {
contentType: ContentTypeReaction,
});
const { sendMessage } = useSendMessage();
const handleClick = useCallback(
(emoji: string) => {
void sendMessage<Reaction>(
conversation,
{
content: emoji,
schema: "unicode",
reference: message.xmtpID,
action: "added",
},
ContentTypeReaction,
);
},
[conversation, message.xmtpID, sendMessage],
);
import org.xmtp.android.library.codecs.ReactionCodec
Client.register(codec = ReactionCodec())
let reaction = Reaction(
reference: messageToReact.id,
action: .added,
content: "U+1F603",
schema: .unicode
)
try await conversation.send(
content: reaction,
options: .init(contentType: ContentTypeReaction)
)
val reaction = Reaction(
reference = messageToReact.id,
action = ReactionAction.added,
content = "U+1F603",
schema = ReactionSchema.unicode
)
conversation.send(
content = reaction,
options = SendOptions(contentType = ContentTypeReaction),
)
// Assuming you have a conversation object and the ID of the message you're reacting to
const reactionContent = {
reaction: {
reference: messageId, // ID of the message you're reacting to
action: "added", // Action can be 'added' or 'removed'
schema: "unicode", // Schema can be 'unicode', 'shortcode', or 'custom'
content: "👍", // Content of the reaction
},
};
await conversation.send(reactionContent);
Receive a reaction
Now that you can send a reaction, you need a way to receive a reaction. For example:
- JavaScript
- React
- Kotlin
- Swift
- Dart
- React Native
if (message.contentType.sameAs(ContentTypeReaction)) {
// We've got a reaction.
const reaction: Reaction = message.content;
}
if (message.contentType === ContentTypeReaction.toString()) {
const reactionContent = message.content as Reaction;
// Use reactionContent...
}
useReactions
Use to fetch all reactions for a specific message. It takes a CachedMessage
as a parameter and returns an array of CachedReaction
objects.
import { useReactions } from "@xmtp/react-sdk";
const reactions = useReactions(message);
getReactionsByXmtpID
Use to retrieve all reactions associated with a specific XMTP ID from the database.
import { getReactionsByXmtpID } from "@xmtp/react-sdk";
const reactions = await getReactionsByXmtpID("testXmtpId1", db);
hasReaction
Use to check if a message has any reactions. It takes a CachedMessage
as a parameter and returns a boolean indicating whether the message has reactions.
import { hasReaction } from "@xmtp/react-sdk";
const messageHasReaction = hasReaction(originalMessage!);
if (message.contentType == ContentTypeReaction) {
// The message is a reaction
val reactionCodec = ReactionCodec()
val reaction: Reaction = reactionCodec.decode(message.content)
}
let content: Reaction = try message.content()
var decoded = await codec.decode(encoded);
if (message.contentTypeId === "xmtp.org/reaction:1.0") {
const reaction = await message.content();
return reaction;
//reaction.reference = id of the message being reacted to,
//reaction.action = 'added',
//reaction.schema = 'unicode',
//reaction.content = '💖',
}
To handle unsupported content types, refer to the fallback section.
Display the reaction
Generally, reactions should be interpreted as emoji. So, "smile" would translate to 😄 in UI clients. That being said, how you ultimately choose to render a reaction in your app is up to you.