skip to Main Content

I want to show a toast when my client side component mounts.
I’m using sonner library to show toast, it’s working fine when we use button to show toast.

I make an example app to show the problem. Here is the github link https://github.com/saifion33/Nextjs-toast-problem

I’m trying to trigger a toast when component mount on client side.

app/layout.tsx

<html lang="en">
  <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
    {children}
    <ToasterComp />
  </body>
</html>

ToasterComp

"use client"

import { Toaster } from "sonner"

const ToasterComp = () => {
  return (
    <Toaster closeButton richColors duration={3000} />
  )
}

export default ToasterComp

app/page.tsx

import MyComponent from "@/components/MyComponent";

export default function Home() {
  return (
    <div className="text-center">
      <h1 className=" my-10 text-blue-500 text-3xl">Sonner render problem example app</h1>
      <p className="text-slate-800">
        Reload this page, if you don&apos;t see a toast then this is not working. if you click the button you will see a toast.
      </p>
      <MyComponent />
    </div>
  );
}

MyComponent

"use client"

import { useEffect } from "react"
import { toast } from "sonner"

const MyComponent = () => {
  useEffect(() => {
    toast.success("This is the toast that will be shown.")
  }, [])

  return (
    <div>
      <button
        className="bg-blue-500 text-stone-50 border-2 border-slate-900 py-2 px-4 rounded-lg mt-4"
        onClick={() => toast.info('You clicked the button.')}
      >
        Show toast
      </button>
    </div>
  )
}

export default MyComponent

2

Answers


  1. Have you tried to use setTimeout or requestAnimateFrame?

    With setTimeout

    setTimeout(() => {
      toast.success("This is the toast that will be shown.")
    })
    

    With requestAnimationFrame

    useEffect(() => {
    const frame = requestAnimationFrame(() => {
      toast.success("This is the toast that will be shown.")
    });
    return () => cancelAnimationFrame(frame); // Cleanup on unmount}, []);
    
    Login or Signup to reply.
  2. I am not sure it would but, maybe try putting Toast component above children

    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
        <ToasterComp />
        {children}
      </body>
    </html>
    

    Or try lazy loading the component with ssr:false, in which you have to show toast on component mount.

    const MyComponent = dynamic(()=>import("@/components/MyComponent"),{ssr:false})
    
    export default function Home() {
      return (
        <div className="text-center">
          <h1 className=" my-10 text-blue-500 text-3xl">Sonner render problem example app</h1>
          <p className="text-slate-800">
            Reload this page, if you don&apos;t see a toast then this is not working. if you click the button you will see a toast.
          </p>
          <MyComponent />
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search