example of SSE streaming

master
Avraham Sakal 2 months ago
parent 2d35a4683b
commit 18411402f5

@ -32,7 +32,12 @@ import {
useMutation, useMutation,
useQuery, useQuery,
} from "@tanstack/react-query"; } from "@tanstack/react-query";
import { createTRPCClient, httpBatchLink } from "@trpc/client"; import {
createTRPCClient,
httpBatchLink,
httpSubscriptionLink,
splitLink,
} from "@trpc/client";
import type { AppRouter } from "../trpc/router.js"; import type { AppRouter } from "../trpc/router.js";
function makeQueryClient() { function makeQueryClient() {
@ -74,9 +79,16 @@ export default function LayoutDefault({
const [trpc] = useState(() => const [trpc] = useState(() =>
createTRPCClient<AppRouter>({ createTRPCClient<AppRouter>({
links: [ links: [
httpBatchLink({ splitLink({
url: "/api/trpc", // uses the httpSubscriptionLink for subscriptions
methodOverride: "POST", condition: (op) => op.type === "subscription",
true: httpSubscriptionLink({
url: "/api/trpc",
}),
false: httpBatchLink({
url: "/api/trpc",
methodOverride: "POST",
}),
}), }),
], ],
}) })

@ -1,25 +1,33 @@
import { Card, Textarea } from "@mantine/core"; import { Card, Textarea } from "@mantine/core";
import { useState } from "react"; import { useState } from "react";
import { useTRPC } from "../../trpc/client"; import { useTRPCClient } from "../../trpc/client";
export default function ChatPage() { export default function ChatPage() {
const [inputMessage, setInputMessage] = useState(""); const [inputMessage, setInputMessage] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [outputMessage, setOutputMessage] = useState(""); const [outputMessage, setOutputMessage] = useState("");
const trpc = useTRPC(); const trpc = useTRPCClient();
async function handleSendMessage() { async function handleSendMessage() {
setLoading(true); setLoading(true);
const response = await trpc.chat.streamMessage.subscribe(
const subscription = trpc.chat.streamMessage.subscribe(
{ {
message: inputMessage, message: inputMessage,
}, },
{} {
onData(value) {
setOutputMessage((prevOutputMessage) => prevOutputMessage + value);
},
onError(error) {
console.error(error);
},
onComplete() {
subscription.unsubscribe();
setLoading(false);
},
}
); );
for await (const chunk of response) {
setOutputMessage(chunk);
}
setLoading(false);
} }
return ( return (
<div> <div>
@ -33,6 +41,7 @@ export default function ChatPage() {
onKeyDown={async (e) => { onKeyDown={async (e) => {
if (e.key === "Enter") { if (e.key === "Enter") {
e.preventDefault(); e.preventDefault();
handleSendMessage();
} }
}} }}
/> />

Loading…
Cancel
Save