use-truapi
Chat

useSendChatMessage

Post a message into a chat room

useSendChatMessage posts messages into a room. Call send(content, roomId?); it resolves to the assigned messageId, and the usual mutation state (data, error, isPending, reset) tracks the last send. Plain strings become Text messages: send("hi") is sugar for sending { tag: "Text", value: { text: "hi" } }; any other ChatMessageContent variant is passed through as-is.

The target room can be set once on the hook or per call: pass roomId to the hook for a fixed room, or as the second argument of send to override it (handy for bots replying into whichever room an action came from). If neither is given, send rejects.

Chat is host-only. Running standalone send rejects with HostUnavailableError; gate the send UI with useIsHost.

Usage

import { useState } from "react";
import { useSendChatMessage } from "@use-truapi/react";

function Composer({ roomId }: { roomId: string }) {
  const { send, isPending, error } = useSendChatMessage(roomId);
  const [draft, setDraft] = useState("");

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        void send(draft).catch(() => {});
        setDraft("");
      }}
    >
      <input value={draft} onChange={(e) => setDraft(e.target.value)} />
      <button type="submit" disabled={isPending || draft === ""}>
        {isPending ? "Sending…" : "Send"}
      </button>
      {error && <p role="alert">{error.message}</p>}
    </form>
  );
}
<script setup lang="ts">
import { ref } from "vue";
import { useSendChatMessage } from "@use-truapi/vue";

const props = defineProps<{ roomId: string }>();
const { send, isPending, error } = useSendChatMessage(() => props.roomId);
const draft = ref("");

function onSubmit() {
  void send(draft.value).catch(() => {});
  draft.value = "";
}
</script>

<template>
  <form @submit.prevent="onSubmit">
    <input v-model="draft" />
    <button type="submit" :disabled="isPending || draft === ''">
      {{ isPending ? "Sending…" : "Send" }}
    </button>
    <p v-if="error" role="alert">{{ error.message }}</p>
  </form>
</template>

In Vue, the hook-level roomId may be a getter for reactive rooms.

In a fire-and-forget handler, void send(draft).catch(() => {}) keeps the promise from going unhandled; the failure still lands in error. Await send instead when you need the result.

Anything beyond plain text is sent as a tagged ChatMessageContent:

const { send } = useSendChatMessage("support");

// Action buttons
const { messageId } = await send({
  tag: "Actions",
  value: {
    text: "Feeling lucky?",
    actions: [{ actionId: "roll", title: "Roll the dice" }],
    layout: "Column",
  },
});

// React to that message
await send({ tag: "Reaction", value: { messageId, emoji: "🎲" } });

To target rooms per call, omit the hook-level roomId (or keep it as a default) and pass the room as the second argument; the call-site room always wins:

const { send } = useSendChatMessage();
void send("Done!", action.roomId).catch(() => {});

See also

API reference

React

function useSendChatMessage(roomId?, options?): NamedMutation<{
  messageId: string;
}, SendChatMessageVariables> & object;

Send into a room: send("hi") or send(content, roomId).

Parameters

ParameterType
roomId?string
options?{ mutation?: MutationOptions<{ messageId: string; }, SendChatMessageVariables>; }
options.mutation?MutationOptions<{ messageId: string; }, SendChatMessageVariables>

Returns

NamedMutation<{ messageId: string; }, SendChatMessageVariables> & object

Properties

content

content: string | ChatMessageContent;

Plain strings become Text messages.


roomId?

optional roomId?: string;

Overrides the roomId given to the hook.

Vue

function useSendChatMessage(roomId?, options?): NamedMutation<{
  messageId: string;
}, SendChatMessageVariables> & object;

Send into a room: send("hi") or send(content, roomId).

Parameters

ParameterType
roomId?MaybeGetter<string | undefined>
options?{ mutation?: MutationOptions<{ messageId: string; }, SendChatMessageVariables>; }
options.mutation?MutationOptions<{ messageId: string; }, SendChatMessageVariables>

Returns

NamedMutation<{ messageId: string; }, SendChatMessageVariables> & object

Properties

content

content: string | ChatMessageContent;

Plain strings become Text messages.


roomId?

optional roomId?: string;

Overrides the roomId given to the composable.

On this page