example of SSE streaming
This commit is contained in:
@@ -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,10 +79,17 @@ export default function LayoutDefault({
|
|||||||
const [trpc] = useState(() =>
|
const [trpc] = useState(() =>
|
||||||
createTRPCClient<AppRouter>({
|
createTRPCClient<AppRouter>({
|
||||||
links: [
|
links: [
|
||||||
httpBatchLink({
|
splitLink({
|
||||||
|
// uses the httpSubscriptionLink for subscriptions
|
||||||
|
condition: (op) => op.type === "subscription",
|
||||||
|
true: httpSubscriptionLink({
|
||||||
|
url: "/api/trpc",
|
||||||
|
}),
|
||||||
|
false: httpBatchLink({
|
||||||
url: "/api/trpc",
|
url: "/api/trpc",
|
||||||
methodOverride: "POST",
|
methodOverride: "POST",
|
||||||
}),
|
}),
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
+17
-8
@@ -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) {
|
||||||
for await (const chunk of response) {
|
setOutputMessage((prevOutputMessage) => prevOutputMessage + value);
|
||||||
setOutputMessage(chunk);
|
},
|
||||||
}
|
onError(error) {
|
||||||
|
console.error(error);
|
||||||
|
},
|
||||||
|
onComplete() {
|
||||||
|
subscription.unsubscribe();
|
||||||
setLoading(false);
|
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();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user