Implementing Chat
Unanswered
Broad-snouted Caiman posted this in #help-forum
Broad-snouted CaimanOP
Hello, I've been working on this feature for the past 2 days and been going around in circles so wanted to see if anyone could give me some help/direction.
It's basically an AI chat which I have most of the functionality built out already but I wanted to make it where the landing page
Relative tech: Using Nextjs 15 app router and
Issue: I can't get it working with streaming + chat history + page route. Usually I can get 2 of them working but not all 3 at the same time.
Due to message limit See next message for what I've tried.
It's basically an AI chat which I have most of the functionality built out already but I wanted to make it where the landing page
/chat would have an empty chat then when the user sends a message the page would route to /chat/[chatId] and then start streaming the response from the AI. ChatGBT does the same thing if you want a visual representation.Relative tech: Using Nextjs 15 app router and
useChat hook from '@ai-sdk/react'.Issue: I can't get it working with streaming + chat history + page route. Usually I can get 2 of them working but not all 3 at the same time.
Due to message limit See next message for what I've tried.
15 Replies
Broad-snouted CaimanOP
## What I've tried
### Version 1 - hook
Using the hook in
But if on
The route changes causes the streaming to not be received for some reason which isn't fully clear to me. If I just comment out the
### Version 2 - context
The same hook (with small adjustments) now lives in a provider that wraps the layout.tsx children under /chat. Provider reads the route params then feeds it into the chat hook. Due to living in layout context it now lives between page routing so sending message in
But the issue is now is loading the initial messages. From my understanding its generally bad to fetch data in the layout so not sure how I'm suppose to feed the context/hook the intial messages from the db. So wasn't fully sure if its approach is the correct one.
### Version 1 - hook
Using the hook in
chat-view.tsx component that accepts the intial messages through a prop that was fetched on the server component. Then the hook handles the state and just using the params hook I check if we're on /chat or /chat/[chatId]. If on /chat/[chatId] just send the message & chatId to route, save user message on route and stream response and on stream finish it saves the response to the db. But if on
/chat then create a chat entry in db, return the id, then send message & chatId to same route. Then without awaiting just route.replace(/chat/[conversationId]).The route changes causes the streaming to not be received for some reason which isn't fully clear to me. If I just comment out the
route.replace(/chat/[conversationId]) then the streaming is received.### Version 2 - context
The same hook (with small adjustments) now lives in a provider that wraps the layout.tsx children under /chat. Provider reads the route params then feeds it into the chat hook. Due to living in layout context it now lives between page routing so sending message in
/chat will route to /chat/[chatId] and updating the state with user message and receive the stream. But the issue is now is loading the initial messages. From my understanding its generally bad to fetch data in the layout so not sure how I'm suppose to feed the context/hook the intial messages from the db. So wasn't fully sure if its approach is the correct one.
I've found there's another way to share state across components here https://ai-sdk.dev/cookbook/next/use-shared-chat-context but I feel like I've been running in circles and a bit lost now so unsure if this is the correct way to go.
Broad-snouted CaimanOP
Sorry a bit confused as I used the
Also the goal is to have an empty chat on
Would useSelectedLayoutSegments() help in this instance? I looked at the documentation a bit and at first glance it doesn't seem like it but maybe I'm not fully understanding it.
useRouter hook for router.replace() from https://nextjs.org/docs/15/app/api-reference/functions/use-router. Also the goal is to have an empty chat on
/chat then when the user sends a message the path changes to /chat/[id] while also receiving a stream response from a route.ts.Would useSelectedLayoutSegments() help in this instance? I looked at the documentation a bit and at first glance it doesn't seem like it but maybe I'm not fully understanding it.
Longtail tuna
/chat/[[...id]] (optional catch all slug) and you should be fineif id is Array#Unknown Channel [string] -> lookup associated chat, otherwise redirect to
/chat@Longtail tuna `/chat/[[...id]]` (optional catch all slug) and you should be fine
Broad-snouted CaimanOP
Hey I appreciate the response but it seems like you're trying to solve an issue with seeing what the ID is.
I don't believe the issue is with catching the id. I believe the issue is transitioning from /chat route to chat/[id] the the component gets unmounted and remounted which the life cycle of the the hook that a holds the chat state which in turn loses the connection to the stream response.
Unless you see something I don't and this does somehow help me then I'd like a bit more details please.
I don't believe the issue is with catching the id. I believe the issue is transitioning from /chat route to chat/[id] the the component gets unmounted and remounted which the life cycle of the the hook that a holds the chat state which in turn loses the connection to the stream response.
Unless you see something I don't and this does somehow help me then I'd like a bit more details please.
Longtail tuna
if i understood ur issue, you can do something like
// /chat/layout.tsx
export default function ChatLayout(...) {
return <ContextThatHoldsConnection>{...}</ContextThatHoldsConnection>;
}// /chat/[[...id]]/page.tsx
export default function ChatPage(...) {
const id = ...;
const chat = ...;
return <Chat chat={chat} />;
}then in Chat component you would render either chat with history or just empty chat
and ContextThatHoldsConnection wouldn't be unmounted between navigations under
/chat (so /chat to /chat/<id>, /chat/<id> to /chat shouldn't reset ur connection)@Longtail tuna and ContextThatHoldsConnection wouldn't be unmounted between navigations under `/chat` (so `/chat` to `/chat/<id>`, `/chat/<id>` to `/chat` shouldn't reset ur connection)
Broad-snouted CaimanOP
Yes, I tried with a context in version 2 but the issue is now is loading the initial messages. From my understanding its generally bad to fetch data in the layout so not sure how I'm suppose to feed the context/hook the intial messages from the db. So wasn't fully sure if its approach is the correct one.
Longtail tuna
ur not fetching data in layout here but in
ChatPage which is page (const chat = ...)in
ChatLayout you can wrap page/children within suspense to provide some fallbackeither way you should be fine
Broad-snouted CaimanOP
I guess I'm having troubles figuring out what
chat is in your code. If its the chat messages from the db then I can't feed it to the hook that lives in the layout from what I understand. At least not on the server component so i believe it will most likely flash the old chat before getting updated.