(vue) useChat not responsive to changes in the conversation ID
Description
In Vue it is impossible to change id for useChat component based on a prop value (or a route parameter), since properties are reactive and id value must be fixed at setup stage.
Code example
// App.vue
<script setup lang="ts">
import Chat from "./components/Chat.vue";
import { ref } from "vue";
const chatId = ref("123");
</script>
<template>
<input v-model="chatId" type="number" />
<p>
{{ chatId }}
</p>
<Chat :chatId />
</template>
// Chat.vue
<template>
<p>{{ chatId }}</p>
<p>{{ id }}</p>
</template>
<script setup lang="ts">
import { useChat } from "@ai-sdk/vue";
const props = defineProps<{ chatId: string }>();
const { id } = useChat({ id: props.chatId });
</script>
AI provider
No response
Additional context
Differently from React, the setup function is not re-executed every time props change, but rather the properties themselves are reactive.
The standard pattern for Vue composables that have to react to their input is to accept a MaybeRef<T> as a parameter and use computed/watch/watchEffect to handle changes to the parameter, rather than rely on useChat being invoked again when they change.
I'm having the same issue. did you find a work around @pqnet?
I'm having the same issue. did you find a work around @pqnet?
The workaround is to use ref to force the component that hosts useChat to be recreated when it changes. Which is usually all the page. This is quite ugly but at least it works. Alternatively you can keep the same fictitious id in useChat and manually remove and reload all messages when the conversation changes. Third you can ditch it completely and write your own, either using the undocumented low level response/stream parsing functions inside ai-sdk or manually implementing your own (the stream format is documented and specified)
The workaround is to use
refto force the component that hostsuseChatto be recreated when it changes. Which is usually all the page. This is quite ugly but at least it works.
It is not only ugly, but won't work either.
Consider this use case: user switches to another chat before the first one completes streaming, and then comes back to the first, and hit the stop button.
If you force the component to rerender in order to respond to a reactive id, useChat will be called again, which will return a different stop function, which won't cancel the initial unfinished stream.
The current vue composable implementation is very largely not reactive, which makes it very difficult to work with. I think the API should be more native to vue instead of a mimic of the react one.
I'm having the same issue, we have some news ?
in ai sdk 5 you cannot change the chat by changing the id any more
@lgrammel sorry but i have a question, because i'm creating a clone of chatgpt for myself, with sidebar chats ecc... And when i'm starting to chat with the assistant i'm going to take the ChatID and save the messages in a KV with this ID. But I need the possibility if i close the blog, after 1 month go back in the old chat i wanna retrieve the last messages a continue to chatting and save in the same KV ID. This is no more possibile right ? Can you give me an alternative ?
should be possible. with vue you can create a new chat instance with the new id and messages, and then use resume (if you have resumable streams set up)
should be possible. with vue you can create a new chat instance with the new id and messages, and then use resume (if you have resumable streams set up)
The issue is exactly about that: how do you create a new chat instance? useChat does not allow us to do that. Lifetime in Vue does not work as in React. Code in setup function in Vue is only executed once in the lifetime of a component, composables are supposed to be able to adapt to a change in their parameters.
Normally we could force creating a new chat instance every time the id changes by doing something like this:
const id = ref(...);
const chatref = computed(() => useChat(id.value))
But this doesn't work because useChat registers lifetime hooks, and as such it must be called on top level setup() scope.
For an explanation of why reactivity in Vue works differently than in React, see tutorial at https://vuejs.org/guide/reusability/composables#async-state-example
@lgrammel Can you please reopen this issue?
Looking at the code I can see that a new low level Chat class is available in the 2.0 beta version of the library, and the useChat composable has been removed. It is now[^beta] possible to do
const id = ref(...);
const chatref = computed(() => new Chat(id.value))
[^beta]: using @ai-sdk/vue@beta
Looking at the code I can see that a new low level
Chatclass is available in the 2.0 beta version of the library, and theuseChatcomposable has been removed. It is now1 possible to doconst id = ref(...); const chatref = computed(() => new Chat(id.value))
Footnotes
1. using `@ai-sdk/vue@beta` [↩](#user-content-fnref-beta-77612ce6a5a825f8d652e478dc0439b5)
Version 2 is now stable. Closing the issue.