[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live)

[AI SDK](/c/ai-sdk/62)

# There is lag when its try to get a respond to write at React marker

175 views · 2 likes · 3 posts


3frotodev (@3frotodev) · 2025-02-11

<!-- Questions that get answered the fastest are the ones with relevant info included in the original post. Be sure to include all detail needed to let others see and understand the problem! -->

<!-- Current versus Expected behavior -->
The AI ​​speech should be written quickly and not in this way, so that the site stops for about 5 seconds until the AI ​​finishes its speech in a strange way, as I will attach in the video. This is a very annoying reality. I have been in this problem for a week and I cannot find a solution. I am even starting to lose hope in the project. I will attach all the codes and all the pictures that are posted. What is happening?

[image] 


<!-- Code, configuration, and steps that reproduce this issue -->

![image|690x455](upload://8XKwNS9zgFFM80yJPpTUhIoYmOp.jpeg)

https://streamable.com/h2qy2g
```tsx
/* eslint-disable @typescript-eslint/no-unused-vars */
"use client"

import { Chat } from "@/components/ui/chat";
import { AppSidebar } from "../components/app-sidebar"
import { Icon } from "@iconify/react";
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import { Form } from '@heroui/form';
import { Badge } from '@heroui/badge'
import { Button, Card, CardBody, CardFooter, CardHeader, Divider, Link } from '@heroui/react';
import Image from "next/image";
import { Input, Textarea } from '@heroui/input'
import { Avatar } from '@heroui/avatar';
import { Tooltip } from '@heroui/tooltip';
import ProseMirrorMarkdownEditor from "@/components/ProseMirrorMarkdownEditor";
import { SidebarInset, SidebarProvider, SidebarTrigger, useSidebar } from "@/components/ui/sidebar"
import { useChat } from "ai/react"
import { useSession } from "next-auth/react";
import { Spinner } from "@heroui/spinner"
import Cookies from "js-cookie";
import { useEffect, useState } from "react";
import { Logo, SideBarPhoneIcon, SideBarPhoneIcon2 } from "@/components/icons";
import SyntaxHighlighter from "react-syntax-highlighter";
import { dark } from "react-syntax-highlighter/dist/esm/styles/prism";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { ButtonGroup, Chip, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger } from "@heroui/react";
import { useTheme } from "next-themes";
import Header from "@/components/Header";
import { toast } from "sonner";
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard";

export default function Page() {
  const {
    messages,
    input,
    handleInputChange,
    handleSubmit,
    append,
    reload,
    error,
    isLoading,
    stop,
  } = useChat()
  const session = useSession()
  const { open, toggleSidebar, isMobile } = useSidebar()
  const [selectedAi, setSelectedAi] = useState("DeepSeek R1")
  const { theme, setTheme } = useTheme();
  const savedTheme = Cookies.get("theme");
  const [copied, setcopy] = useState(false)
  const [src, setsrc] = useState("/LogoBlack.png")
  const handleCopy = (input: string) => {
    if(copied) return;
    navigator.clipboard.writeText(input)
      .then(() => {
        setcopy(true)
        setTimeout(() => {
          setcopy(false);
        }, 5000);
      })
      .catch((err) => {
        toast.error("Can't copy :(")
      });
  };

  return (
    <>
      <AppSidebar />

      <SidebarInset>
        <header className="flex h-16 shrink-0 sticky top-0 z-30 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12 border-b-small bg-white dark:bg-background dark:border-sidebar-border border-gray-200">
          <div className="flex items-center gap-2 px-4">
            {!isMobile ? (
              open ? null : (
                <>
                  <Button
                    isIconOnly
                    variant='light'
                    onPress={toggleSidebar}
                  >
                    {
                      isMobile ? <SideBarPhoneIcon2 size={25} /> : <Icon icon="solar:siderbar-outline" width={25} />
                    }
                  </Button>
                  <Divider orientation="vertical" className="mr-2 h-4" />
                </>
              )
            ) : (
              <>
                <Button
                  isIconOnly
                  variant='light'
                  onPress={toggleSidebar}
                >
                  {
                    isMobile ? <SideBarPhoneIcon2 size={25} /> : <Icon icon="solar:siderbar-outline" width={25} />
                  }
                </Button>
                <Separator orientation="vertical" className="mr-2 h-4" /></>
            )}
            <Dropdown>
              <DropdownTrigger>
                <Button className="sm:max-w-none max-w-24 text-foreground-400" startContent={<Icon icon="svg-spinners:blocks-scale" />} variant='light' >{selectedAi}</Button>
              </DropdownTrigger>
              <DropdownMenu aria-label="Example with disabled actions" selectedKeys={[selectedAi]}>
                <DropdownItem onSelect={() => setSelectedAi("Gemini")} endContent={<Chip size='sm' radius='lg' color='warning' className="text-[#C9A9E9] bg-[#643b8d]">Pro</Chip>} key="gemini">Gemini</DropdownItem>
                <DropdownItem onSelect={() => setSelectedAi("DeepSeek R1")} endContent={<Chip size='sm' radius='full' className="text-[#17C946] bg-[#17c94680]" color="success">New</Chip>} key="deepseek">DeepSeek R1</DropdownItem>
              </DropdownMenu>
            </Dropdown>
          </div>
        </header>
        {messages.length === 0 ? (
          <div id="scroll-auto">
            <div className="flex-grow flex flex-col items-center gap-4 justify-center min-h-[656px] pb-[5%]">

              <div className="justify-start items-start">
                <Logo size={150} />
              </div>
              <div className="text-center">
                <h1 className="text-4xl font-bold ">Hi, I&apos;m EgyAI.</h1>
                <p className="text-xl text-gray-600 mt-4">How can I help you today?</p>
              </div>
              <div
                id="search-bar"
                className="relative w-full flex flex-col justify-center items-center gap-4"
              >
                <Textarea
                  className="max-w-[800px] flex flex-col justify-between w-full rounded-2xl border-medium px-3 py-2 pt-3 gap-1.5 hover:border-gray-400 transition-colors duration-200"
                  onChange={handleInputChange}
                  autoFocus
                  value={input}
                  placeholder="Ask EgyAI..."
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && !e.shiftKey) {
                      e.preventDefault();
                      handleSubmit();
                    }
                  }}
                  endContent={
                    <>
                      <Button size="sm" onPress={() => handleSubmit()} variant='light' fullWidth isIconOnly><Icon width={32} icon="solar:link-circle-bold" /></Button>
                      <Tooltip closeDelay={3} content={`${input.length === 0 ? "Empty Message" : ""}`}>
                        <div style={{ cursor: `${input.length === 0 ? 'not-allowed' : ""}` }}>
                          <Button isDisabled={input.length === 0} size="sm" onPress={() => (isLoading ? stop() : handleSubmit())} variant='light' fullWidth isIconOnly><Icon width={32} icon={isLoading ? "solar:stop-circle-bold" : "solar:round-arrow-up-bold"} /></Button>
                        </div>
                      </Tooltip>
                    </>
                  }
                  classNames={{
                    base: "border-none"
                  }}
                />
              </div>
            </div>
          </div>
        ) : (<>
          <div className="flex flex-col overflow-auto px-3 w-full mx-auto h-full justify-between">
            <div className="w-full md:max-w-4xl mx-auto pt-4 pb-2 px-4">
              <div className="flex gap-12">
                <div className="flex-grow flex flex-col gap-1 relative items-center max-w-full">
                  <div id="qa-container">
                    <div id="message" className="flex gap-12 flex-col min-h-0">
                      <div className="flex-grow flex flex-col gap-2">
                        <div className="flex-grow flex flex-col gap-2">
                          {messages.map(message => (
                            <div key={message.id} className="w-full">
                              {message.role === 'user' ?
                                <>
                                  <article
                                    className="w-full text-token-text-primary focus-visible:outline-2 focus-visible:outline-offset-[-4px]"
                                    dir="auto"
                                    data-testid="conversation-turn-2"
                                    data-scroll-anchor="false"
                                  >
                                    <h5 className="sr-only">User said:</h5>
                                    <div className="m-auto text-base py-[18px] px-6">
                                      <div className="mx-auto flex flex-1 gap-4 text-base md:gap-5 lg:gap-6 md:max-w-3xl lg:max-w-[40rem] xl:max-w-[48rem]">
                                        <div className="group/conversation-turn relative flex w-full min-w-0 flex-col @xs/thread:px-0 @sm/thread:px-1.5 @md/thread:px-4">
                                          <div className="flex-col gap-1 md:gap-3">
                                            <div className="flex max-w-full flex-col flex-grow">
                                              <div
                                                data-message-author-role="user"
                                                data-message-id={message.id}
                                                dir="auto"
                                                className="min-h-8 text-message overflow-x-hidden flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5"
                                              >
                                                <div className="flex w-full flex-col gap-1 empty:hidden items-end rtl:items-start">
                                                  <Card className="relative w-fit max-w-[70vw] sm:max-w-[70%] rounded-3xl px-5 py-2.5">
                                                    {message.content}
                                                  </Card>
                                                </div>
                                              </div>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </article>
                                  <div className="min-w-[70vw]" id="look-saver cuz i'm noob at frontend"></div>
                                </>
                                :

                                <article
                                  className="w-full text-token-text-primary focus-visible:outline-2 focus-visible:outline-offset-[-4px]"
                                  dir="auto"
                                  data-testid="conversation-turn-3"
                                  data-scroll-anchor="true"
                                >
                                  <h6 className="sr-only">EgyAi said:</h6>
                                  <div className="m-auto text-base py-[18px] px-6">
                                    <div className="mx-auto flex flex-1 gap-4 text-base md:gap-5 lg:gap-6 md:max-w-3xl lg:max-w-[40rem] xl:max-w-[48rem]">
                                      <div className="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn @xs/thread:px-0 @sm/thread:px-1.5 @md/thread:px-4">
                                        <div className="flex-col gap-1 md:gap-3">
                                          <div className="flex max-w-full flex-col flex-grow">
                                            <div
                                              data-message-author-role="assistant"
                                              data-message-id={message.id}
                                              dir="auto"
                                              className="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5"
                                              data-message-model-slug={selectedAi}
                                            >
                                                   <ProseMirrorMarkdownEditor initialMarkdown={message.content } />

                                            </div>
                                          </div>
                                          <div className="mb-2 flex gap-3 empty:hidden -ml-2">
                                            <div className="items-center justify-start rounded-xl p-1 flex">
                                              <div className="flex items-center">
                                                <Tooltip content="SOON" placement='bottom' closeDelay={3}>
                                                  <Button disabled isIconOnly fullWidth size="sm" variant='light'><Icon width={23} icon="solar:volume-loud-linear" /></Button>
                                                </Tooltip>
                                                <Tooltip content="Copy" placement='bottom' closeDelay={3}>
                                                  <Button onPress={() => handleCopy(message.content)} isIconOnly fullWidth size="sm" variant='light'>{copied ? <Icon width={23} icon="solar:check-read-linear" /> : <Icon width={23} icon="solar:copy-linear" />}</Button>
                                                </Tooltip>
                                                <div className="flex">
                                                  <Tooltip content="Good response" placement='bottom' closeDelay={3}>
                                                    <Button disabled isIconOnly fullWidth size="sm" variant='light'><Icon width={23} icon="solar:like-linear" /></Button>
                                                  </Tooltip>
                                                  <Tooltip content="Bad response" placement='bottom' closeDelay={3}>
                                                    <Button disabled isIconOnly fullWidth size="sm" variant='light'><Icon width={23} icon="solar:dislike-linear" /></Button>
                                                  </Tooltip>
                                                </div>
                                                <span className="hidden" />
                                                <Tooltip content="Reload response" placement='bottom' closeDelay={3}>
                                                  <Button onPress={() => reload()} isIconOnly fullWidth size="sm" variant='light'><Icon width={23} icon="solar:refresh-linear" /></Button>
                                                </Tooltip>
                                              </div>
                                            </div>
                                          </div>
                                          <div className="pr-2 lg:pr-0" />
                                          <div className="mt-3 w-full empty:hidden">
                                            <div className="text-center" />
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </article>}
                            </div>
                          ))}
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>

          </div>
          <div className="sticky bottom-0 mx-auto md:max-w-4xl flex justify-center z-30 w-full px-4 py-4 bg-background">
            <Textarea
              className="max-w-[800px] flex flex-col justify-between w-full rounded-2xl border-medium px-3 py-2 pt-3 gap-1.5 hover:border-gray-400 transition-colors duration-200"
              onChange={handleInputChange}
              autoFocus
              placeholder="Ask EgyAI..."
              value={input}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                  e.preventDefault();
                  handleSubmit();
                }
              }}
              description="Keep in mind EgyAI can make mistakes,Check important information"
              endContent={
                <>
                  <Button size="sm" onPress={() => handleSubmit()} variant='light' fullWidth isIconOnly><Icon width={32} icon="solar:link-circle-bold" /></Button>
                  <Tooltip closeDelay={3} content={`${(isLoading ? false : input.length === 0) ? "Empty Message" : ""}`}>
                    <div style={{ cursor: `${(isLoading ? false : input.length === 0) ? 'not-allowed' : ""}` }}>
                      <Button isDisabled={(isLoading ? false : input.length === 0)} size="sm" onPress={() => (isLoading ? stop() : handleSubmit())} variant='light' fullWidth isIconOnly><Icon width={32} icon={isLoading ? "solar:stop-circle-bold" : "solar:round-arrow-up-bold"} /></Button>
                    </div>
                  </Tooltip>
                </>
              }

              classNames={{
                description: "text-center",
                base: "border-none"
              }}
            />
          </div>
        </>)}
      </SidebarInset >
    </>
  )
}
```
MarkDown
```tsx
import React, { useEffect, useRef } from "react";
import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { schema } from "prosemirror-schema-basic";
import { defaultMarkdownParser } from "prosemirror-markdown";
import hljs from "highlight.js"; // Import highlight.js
import "highlight.js/styles/github-dark.css"; // Choose any theme

// Function to apply syntax highlighting to code blocks
function addCodeHighlighting(view) {
  const codeBlocks = view.dom.querySelectorAll("pre code");
  codeBlocks.forEach((block) => {
    hljs.highlightElement(block); // Apply syntax highlighting
  });
}

// Create a ProseMirror state
function createEditorState(markdownContent) {
  const doc = defaultMarkdownParser.parse(markdownContent);
  return EditorState.create({ doc });
}

// React component for a read-only ProseMirror Markdown viewer
function ProseMirrorMarkdownViewer({ initialMarkdown }) {
  const editorRef = useRef(null);
  const viewRef = useRef(null);

  useEffect(() => {
    // Initialize the editor
    const state = createEditorState(initialMarkdown);
    const view = new EditorView(editorRef.current, {
      state,
      dispatchTransaction(transaction) {
        const newState = view.state.apply(transaction);
        view.updateState(newState);
        addCodeHighlighting(view); // Highlight after updates
      },
      editable: () => false, // Disable editing
    });

    viewRef.current = view;
    addCodeHighlighting(view); // Initial highlighting

    // Cleanup on unmount
    return () => {
      view.destroy();
    };
  }, [initialMarkdown]);

  return <div ref={editorRef} className="prosemirror-container" />;
}

export default ProseMirrorMarkdownViewer;
```

<!-- Project information (URL, framework, environment, project settings) -->

```json
{
  "name": "egpyt-gpt-chat",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@ai-sdk/deepseek": "^0.1.8",
    "@ai-sdk/fal": "^0.0.2",
    "@ai-sdk/fireworks": "^0.1.8",
    "@ai-sdk/google": "^1.1.8",
    "@ai-sdk/groq": "^1.1.7",
    "@ai-sdk/openai": "^1.1.9",
    "@codemirror/highlight": "^0.19.8",
    "@codemirror/lang-python": "^6.1.7",
    "@codemirror/theme-one-dark": "^6.1.2",
    "@fal-ai/client": "^1.2.3",
    "@heroui/react": "^2.6.14",
    "@iconify/react": "^5.2.0",
    "@mdx-js/loader": "^3.1.0",
    "@mdx-js/react": "^3.1.0",
    "@nanostores/react": "github:ai/react",
    "@next/env": "^15.1.6",
    "@next/mdx": "^15.1.6",
    "@prose-ui/core": "^1.0.4",
    "@prose-ui/next": "^1.0.4",
    "@radix-ui/react-avatar": "^1.1.2",
    "@radix-ui/react-collapsible": "^1.1.2",
    "@radix-ui/react-dialog": "^1.1.5",
    "@radix-ui/react-dropdown-menu": "^2.1.5",
    "@radix-ui/react-separator": "^1.1.1",
    "@radix-ui/react-slot": "^1.1.1",
    "@radix-ui/react-switch": "^1.1.2",
    "@radix-ui/react-tooltip": "^1.1.7",
    "@react-aria/ssr": "^3.9.7",
    "@tabler/icons-react": "^3.29.0",
    "@tiptap/core": "^2.11.5",
    "@tiptap/react": "^2.11.5",
    "@tiptap/starter-kit": "^2.11.5",
    "@types/mdx": "^2.0.13",
    "@types/react-syntax-highlighter": "^15.5.13",
    "ai": "^4.1.16",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "codemirror": "^6.0.1",
    "date-fns": "^4.1.0",
    "framer-motion": "^11.18.2",
    "geist": "^1.3.1",
    "highlight.js": "^11.11.1",
    "js-cookie": "^3.0.5",
    "lucide-react": "^0.474.0",
    "next": "14.2.16",
    "next-auth": "^4.24.11",
    "next-themes": "^0.4.4",
    "react": "^18",
    "react-dom": "^18",
    "react-markdown": "^9.0.3",
    "react-remarkable": "^1.1.3",
    "react-resizable": "^3.0.5",
    "react-syntax-highlighter": "^15.6.1",
    "rehype-highlight": "^7.0.2",
    "remark-gfm": "^4.0.0",
    "remarkable-react": "^1.4.3",
    "remeda": "^2.20.0",
    "shiki": "^2.3.2",
    "sonner": "^1.7.4",
    "tailwind-merge": "^3.0.1",
    "tailwindcss-animate": "^1.0.7",
    "tiptap-markdown": "^0.3.4",
    "usehooks-ts": "^3.1.1"
  },
  "devDependencies": {
    "@iconify-json/solar": "^1.2.2",
    "@types/js-cookie": "^3.0.6",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "@types/react-resizable": "^3.0.8",
    "@types/remarkable": "^2.0.8",
    "eslint": "^8",
    "eslint-config-next": "14.2.16",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}
```


Nico Albanese (@nicoalbanese) · 2025-02-11 · ♥ 1

This is likely a performance issue due to how you are rendering the AI response.

Check out our memoization recipe that improve performance and reduce the number of re-renders.
https://sdk.vercel.ai/cookbook/next/markdown-chatbot-with-memoization


3frotodev (@3frotodev) · 2025-02-11 · ♥ 1

thanks its working good now