Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No toast shown in Nextjs 13 #963

Closed
qnxdev opened this issue May 20, 2023 · 8 comments
Closed

No toast shown in Nextjs 13 #963

qnxdev opened this issue May 20, 2023 · 8 comments

Comments

@qnxdev
Copy link

qnxdev commented May 20, 2023

Report Bug

No toast shown

Nextjs 13

Install package
Import react-toastify css in /src/app/layout.tsx
Import and place it in JSX in /src/app/layout.tsx
Call toast("hi) in any page.

Toast should appear

Nextjs 13
Brave browser

@qnxdev
Copy link
Author

qnxdev commented May 20, 2023

Solution: I was able to solve this by adding to the current page at /app/myPage/page.tsx

Seems like a temporary solution but fine with me

@qnxdev qnxdev closed this as completed May 20, 2023
@nokwin
Copy link

nokwin commented May 25, 2023

@qnxdev You need wrap <ToastContainer /> into new client component.

Here how it's done on my side

toast.provider.tsx

"use client";

import { ToastContainer } from "react-toastify";

interface ToastProviderProps {
  children: React.ReactNode;
}

export default function ToastProvider({ children }: ToastProviderProps) {
  return (
    <>
      {children}
      <ToastContainer />
    </>
  );
}

I've put <ToastProvider /> into body element

app/layout.tsx

import { getUserFromSession } from "@/actions/auth";
import Navbar from "@/components/navbar.component";
import AuthProvider from "@/providers/auth.provider";
import ToastProvider from "@/providers/toast.provider";
import Link from "next/link";
import "./globals.css";

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const user = await getUserFromSession();

  return (
    <AuthProvider user={user}>
      <html lang="en">
        <body suppressHydrationWarning>
          <ToastProvider>
            <header className="bg-amber-400 h-16 flex items-center px-4 mb-4">
              <Link href="/" className="text-2xl mr-4">
                Fast Parcel
              </Link>
              <Navbar />
            </header>
            {children}
            <footer className="text-center my-4">
              &copy; 2023 Fast Parcel
            </footer>
          </ToastProvider>
        </body>
      </html>
    </AuthProvider>
  );
}

@matheusgit1
Copy link

don't forget to import toast css

`
"use client";
import "react-toastify/dist/ReactToastify.css"; //add this line

import { ToastContainer } from "react-toastify";

interface ToastProviderProps {
children: React.ReactNode;
}

export default function ToastProvider({ children }: ToastProviderProps) {
return (
<>
{children}

</>
);
}

@MarcinSkic
Copy link

Simplest solution is to not even use {children}, just create client side wrapper and put it in root wherever you need (layout for example). CSS import is very important, without it nothing happens

"use client";

import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

export default function ToastContainerWrapper() {
    return (
        <ToastContainer position={toast.POSITION.BOTTOM_CENTER} theme="dark" />
    );
}

Example usage:

export default function Layout({ children }: React.PropsWithChildren) {

    return (
        <div className={styles["component-default-layout"]}>
            <aside>
                <a href="/">Home</a>
                <a href="/all">Everything list</a>
                <a href="/movie/all">Movies table</a>
                <a href="/person/all">People table</a>
            </aside>
            <main className="content">{children}</main>
            <ToastContainerWrapper />
        </div>
    );
}

@Ngash01
Copy link

Ngash01 commented Nov 2, 2023

@nokwin your I did exactly how you implemented it and it worked!

@IvanAdmaers
Copy link

Simplest solution is to not even use {children}, just create client side wrapper and put it in root wherever you need (layout for example). CSS import is very important, without it nothing happens

"use client";

import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

export default function ToastContainerWrapper() {
    return (
        <ToastContainer position={toast.POSITION.BOTTOM_CENTER} theme="dark" />
    );
}

Example usage:

export default function Layout({ children }: React.PropsWithChildren) {

    return (
        <div className={styles["component-default-layout"]}>
            <aside>
                <a href="/">Home</a>
                <a href="/all">Everything list</a>
                <a href="/movie/all">Movies table</a>
                <a href="/person/all">People table</a>
            </aside>
            <main className="content">{children}</main>
            <ToastContainerWrapper />
        </div>
    );
}

I believe this is the best solution. Provider from @nokwin looks kinda redundant like for me

@rusty120
Copy link

@nokwin Won't including 'use client' in the ToastProvider prevent server-side rending for most of your app? This seems like a big disadvantage, unless I'm missing something?

@MarcinSkic solution isolates the client rendering to just the toast wrapper, which would preferable for most cases.

@MarcinSkic
Copy link

@rusty120 no, there can be server side rendered components as children of client side components, otherwise any ContextProvider would prevent most of the app from being SSR, you can find more information here:
https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#supported-pattern-passing-server-components-to-client-components-as-props and here
vercel/next.js#43153

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants