title | description |
---|---|
Render Markdown Messages |
Learn how to render markdown messages using the `useLopusChat` hook |
This guide will walk you through the process of rendering markdown messages in your React application using the useLopusChat
hook. We'll cover the setup, rendering logic, and best practices to ensure a smooth integration.
- Ensure you have a React application setup
- Complete the quickstart guide
- Install
react-markdown
package
pnpm add react-markdown
yarn add react-markdown
bun add react-markdown
deno install npm:react-markdown@latest
Return messages inside a ReactMarkdown
component instead of a div
:
export function Message({ message }: MessageProps) {
return (
<div
className={mb-2 p-2 rounded ${ message.sender === 'USER' ? 'bg-blue-600 text-white ml-auto' : 'bg-gray-200 text-black' } max-w-[80%]
}
>
{(() => {
switch (typeof message.content) {
case 'string':
return (
{message.content}
);
case 'object':
if (React.isValidElement(message.content)) {
return message.content;
}
return
interface Message { content: string | ReactElement<unknown, string | JSXElementConstructor> | Record<string, unknown>; sender: 'USER' | 'ASSISTANT'; }
interface MessageProps { message: Message; }
```tsx MessageList.tsx
import React, { ReactElement, JSXElementConstructor } from 'react';
import { Message } from './Message';
export function MessageList({ messages, isLoading }: MessageListProps) {
return (
<div className="flex-1 overflow-auto mb-4">
{messages.map((message, index) => (
<Message key={index} message={message} />
))}
{isLoading && <div className="text-gray-500">Loading...</div>}
</div>
);
}
interface Message {
content: string | ReactElement<unknown, string | JSXElementConstructor<any>> | Record<string, unknown>;
sender: 'USER' | 'ASSISTANT';
}
interface MessageListProps {
messages: Message[];
isLoading: boolean;
}
import React, { useState } from 'react';
export function ChatInput({ onSubmit, isLoading }: ChatInputProps) {
const [input, setInput] = useState('');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim()) return;
try {
await onSubmit(input);
setInput('');
} catch (error) {
console.error('Failed to send message:', error);
}
};
return (
<form onSubmit={handleSubmit} className="flex gap-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
className="flex-1 p-2 border rounded text-black placeholder-zinc-400 border-zinc-600 focus:outline-none focus:border-blue-500"
placeholder="Type your message..."
/>
<button
type="submit"
disabled={isLoading}
className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-zinc-600 disabled:text-zinc-400 hover:bg-blue-700"
>
Send
</button>
</form>
);
}
interface ChatInputProps {
onSubmit: (message: string) => Promise<void>;
isLoading: boolean;
}
'use client';
import { useLopusChat } from "lopus-ai";
import { MessageList } from './components/MessageList';
import { ChatInput } from './components/ChatInput';
export default function ChatComponent() {
const { messages, sendQuery, isLoading } = useLopusChat({
apiKey: 'your_api_key_here',
});
return (
<div className="flex flex-col h-screen p-4 bg-gray-100">
<MessageList messages={messages} isLoading={isLoading} />
<ChatInput onSubmit={sendQuery} isLoading={isLoading} />
</div>
);
}
Your Lopus Chat Component can now render markdown messages:
![](/images/lopus_chat_component.png)- Type Safety: Use type guards like
isReceivedMessage
to safely handle different message types. - Error Handling: Wrap
sendQuery
andsendSubmission
calls in try-catch blocks to manage errors effectively. - Component Handling: For messages containing components, ensure they are rendered correctly.
- Cleanup: The hook manages cleanup automatically, but ensure to remove any custom message handlers if added.
By following these steps, you can effectively render markdown messages in your React application using the useLopusChat
hook. This setup allows for a rich, interactive chat experience.