How to stream text with NextJS v14 from server component to client component ? #67501
-
SummaryAt work, I retrieved some code that I need to adapt into a NextJS application. There is a backend API which wraps ChatGPT calls. A client component with a prompt triggers a server action that calls the API when the input is submitted, and the response is given to ndjsonStream (from can-ndjson-stream) to create a reader that gets the stream. However, I don't know how to pass the streamed text to my client component to display it. Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
I had a tiny demo example for this streaming data. Here, I will provide it, and you can play with it. Using the same idea, you can do it with ChatGPT api as well. Here's how to set it up: import { NextResponse } from 'next/server'
export async function GET() {
const response = await fetch('https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json')
const data = await response.json()
const text = data.join(' ')
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
const words = text.split(' ')
for (let word of words) {
const chunk = encoder.encode(word + ' ')
controller.enqueue(chunk)
await new Promise(resolve => setTimeout(resolve, 100))
}
controller.close()
}
})
return new NextResponse(stream)
} Create a new client component in 'use client'
import React, { useState, useEffect } from 'react'
export default function ClientComponent() {
const [text, setText] = useState('')
useEffect(() => {
const fetchStream = async () => {
const response = await fetch('/api/stream')
const reader = response.body?.getReader()
if (reader) {
while (true) {
const { done, value } = await reader.read()
if (done) break
setText(prev => prev + new TextDecoder().decode(value))
}
}
}
fetchStream()
}, [])
return <div style={{ whiteSpace: 'pre-wrap' }}>{text}</div>
} And you can call it in your main page import ClientComponent from './components/ClientComponent'
export default function Home() {
return (
<main>
<h1>Streaming Demo</h1>
<ClientComponent />
</main>
)
} This is a tiny example in general about streaming data using the ReadableStream API, which lets us read pieces of data as they arrive, instead of waiting for the whole thing. Your case is actually easier, because there are built-in functions on top of this API from various libraries. For example, you can use |
Beta Was this translation helpful? Give feedback.
I had a tiny demo example for this streaming data. Here, I will provide it, and you can play with it. Using the same idea, you can do it with ChatGPT api as well. Here's how to set it up:
Creat a new API route
app/api/stream/route.ts
and add this: