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/codec_registry.dart';
import 'package:xmtp/src/content/decoded.dart';
import 'package:xmtp/src/content/text_codec.dart';
import 'package:xmtp/src/content/reaction_codec.dart';
// Registering
var registry = CodecRegistry()..registerCodec(TextCodec());
var codec = ReactionCodec();
codec.setRegistry(registry);
const client = await Client.create(signer, {
env: "production",
codecs: [new ReactionCodec()],
});
Send 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.Reaction
import org.xmtp.android.library.codecs.ReactionAction
import org.xmtp.android.library.codecs.ReactionSchema
import org.xmtp.android.library.codecs.ContentTypeReaction
import org.xmtp.android.library.SendOptions
val reaction = Reaction(
reference = messageToReact.id, // the ID of the message you're reacting to
action = ReactionAction.Added, // the action of the reaction
content = "U+1F603", // the content of the reaction
schema = ReactionSchema.Unicode // the schema of the reaction
)
conversation.send(
content = reaction,
options = SendOptions(contentType = ContentTypeReaction)
)
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 decodedContent = await registry.decode(encoded);
if (decodedContent.contentType == ContentTypeReaction) {
// The message is a reaction.
Reaction receivedReaction = decodedContent.content;
}
if (message.contentTypeId === "xmtp.org/reaction:1.0") {
const reaction = 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.