Let status drive the UI
Spinner, Stop and Send each follow useChat's status.
AI SDK docsai-sdk.dev
submitted: The message has been sent to the API and we're awaiting the start of the response stream.
From ai-sdk and the Chatbot docs.
One boolean or four states
Press Send, then press a pane's Send again fast.
isLoading booleanBad
Requests 0Duplicates 0
const isLoading = status !== 'ready'statusGood
Requests 0Duplicates 0
disabled={status !== 'ready'}'use client';
import { useChat } from '@ai-sdk/react';
export function Chat() {
const { messages, sendMessage, status, stop } = useChat();
const busy = status === 'submitted' || status === 'streaming';
return (
<>
<Messages messages={messages} />
{status === 'submitted' && <Spinner />}
{busy && <button onClick={() => stop()}>Stop</button>}
<button
disabled={status !== 'ready'}
onClick={() => sendMessage({ text: 'Summarize this thread.' })}
>
Send
</button>
</>
);
}
Why it matters, pros and cons
Why it matters
Waiting and streaming need different UI. One boolean spins over text that is already arriving.
Pros
- The spinner shows only before the first token.
- Stop is there exactly while a stream can be stopped.
- No duplicate sends while a reply is in flight.
Cons
- Four states mean four cases to design.
errorneeds its own UI (next pages).- Blocking Send stops queued follow-ups too.