"use client"; import { Attachment, AttachmentPreview, AttachmentRemove, Attachments, } from "@/components/ai-elements/attachments"; import { Message, MessageAction, MessageActions, MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, MessageContent, MessageResponse, MessageToolbar, } from "@/components/ai-elements/message"; import { CopyIcon, RefreshCcwIcon, ThumbsDownIcon, ThumbsUpIcon, } from "lucide-react"; import { nanoid } from "nanoid"; import { memo, useCallback, useState } from "react"; const messages: { key: string; from: "user" | "assistant"; versions?: { id: string; content: string }[]; content?: string; attachments?: { id: string; type: "file"; url: string; mediaType?: string; filename?: string; }[]; }[] = [ { attachments: [ { filename: "palace-of-fine-arts.jpg", id: nanoid(), mediaType: "image/jpeg", type: "file", url: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&h=400&fit=crop", }, { filename: "react-hooks-guide.pdf", id: nanoid(), mediaType: "application/pdf", type: "file", url: "", }, ], content: "How do React hooks work and when should I use them?", from: "user", key: nanoid(), }, { from: "assistant", key: nanoid(), versions: [ { content: `# React Hooks Guide React hooks are functions that let you "hook into" React state and lifecycle features from function components. Here's what you need to know: ## Core Hooks ### useState Adds state to functional components: \`\`\`jsx const [count, setCount] = useState(0); return ( ); \`\`\` ### useEffect Handles side effects (data fetching, subscriptions, DOM updates): \`\`\`jsx useEffect(() => { document.title = \`You clicked \${count} times\`; // Cleanup function (optional) return () => { document.title = 'React App'; }; }, [count]); // Dependency array \`\`\` ## When to Use Hooks - ✅ **Function components** - Hooks only work in function components - ✅ **Replacing class components** - Modern React favors hooks over classes - ✅ **Sharing stateful logic** - Create custom hooks to reuse logic - ❌ **Class components** - Use lifecycle methods instead ## Rules of Hooks 1. Only call hooks at the **top level** (not inside loops, conditions, or nested functions) 2. Only call hooks from **React functions** (components or custom hooks) Would you like to explore more advanced hooks like \`useCallback\` or \`useMemo\`?`, id: nanoid(), }, { content: `React hooks are special functions that let you use React features in function components. The most common ones are: - **useState** - for managing component state - **useEffect** - for side effects like data fetching - **useContext** - for consuming context values - **useRef** - for accessing DOM elements Here's a simple example: \`\`\`jsx function Counter() { const [count, setCount] = useState(0); return ( ); } \`\`\` Which specific hook would you like to learn more about?`, id: nanoid(), }, { content: `Absolutely! React hooks are a powerful feature introduced in React 16.8. They solve several problems: ## Key Benefits 1. **Simpler code** - No need for class components 2. **Reusable logic** - Extract stateful logic into custom hooks 3. **Better organization** - Group related code together ## Most Popular Hooks | Hook | Purpose | |------|---------| | useState | Add state to components | | useEffect | Handle side effects | | useContext | Access context values | | useReducer | Complex state logic | | useCallback | Memoize functions | | useMemo | Memoize values | The beauty of hooks is that they let you reuse stateful logic without changing your component hierarchy. Want to dive into a specific hook?`, id: nanoid(), }, ], }, ]; const handleCopy = (content: string) => { navigator.clipboard.writeText(content); }; const handleRetry = () => { console.log("Retrying..."); }; interface LikeActionProps { messageKey: string; isLiked: boolean; onToggle: (key: string) => void; } const LikeAction = memo( ({ messageKey, isLiked, onToggle }: LikeActionProps) => { const handleClick = useCallback( () => onToggle(messageKey), [messageKey, onToggle] ); return ( ); } ); LikeAction.displayName = "LikeAction"; interface DislikeActionProps { messageKey: string; isDisliked: boolean; onToggle: (key: string) => void; } const DislikeAction = memo( ({ messageKey, isDisliked, onToggle }: DislikeActionProps) => { const handleClick = useCallback( () => onToggle(messageKey), [messageKey, onToggle] ); return ( ); } ); DislikeAction.displayName = "DislikeAction"; interface CopyActionProps { content: string; } const CopyAction = memo(({ content }: CopyActionProps) => { const handleClick = useCallback(() => handleCopy(content), [content]); return ( ); }); CopyAction.displayName = "CopyAction"; const Example = () => { const [liked, setLiked] = useState>({}); const [disliked, setDisliked] = useState>({}); const handleToggleLike = useCallback((key: string) => { setLiked((prev) => ({ ...prev, [key]: !prev[key] })); }, []); const handleToggleDislike = useCallback((key: string) => { setDisliked((prev) => ({ ...prev, [key]: !prev[key] })); }, []); return (
{/* biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Demo component with complex rendering logic */} {messages.map((message) => ( {message.versions?.length && message.versions.length > 1 ? ( {message.versions?.map((version) => ( {version.content} ))} {message.from === "assistant" && ( v.id)?.content || "" } /> )} ) : (
{message.attachments && message.attachments.length > 0 && ( {message.attachments.map((attachment) => ( ))} )} {message.from === "assistant" ? ( {message.content} ) : ( message.content )} {message.from === "assistant" && message.versions && ( )}
)}
))}
); }; export default Example;