1

I'm using Next.js 14 with the app router.

I have two server components:

  1. List page /products that shows multiple products
  2. Product Details page /products/{id}.

On /products/{id} I check whether the id is available in my products database with a server action and then render the product.

If the product is not available, I wanted to redirect the user back to /products and show a toast message that the product was not found.

Redirecting is simple enough:

import { redirect } from 'next/navigation'

async function getNoProduct() {
  return null
}

export default async function RedirectFromPage() {
  
  let res = await getNoProduct()
  if (!res === null) {
    redirect('/products')
  }
  return (
    <div>
      <p>Hello SO</p>
    </div>
  )
}

However, I'm stuck implementing the toast message (using sonner toast via shadcn).

Directly adding the toast like below doesn't work because /products/{id} is a server component and toast relies on useEffect, e.g.

import { redirect } from 'next/navigation'
import { useToast } from '@/components/ui/use-toast'

async function getNoProduct() {
  return null
}

export default async function RedirectFromPage() {
  const { toast } = useToast()

  let res = await getNoProduct()
  if (!res === null) {
    // Show toast
    toast({
      title: 'Error',
      description: 'Product not found',
    })
    redirect('/products')
  }
  return (
    <div>
      <p>Hello SO</p>
    </div>
  )
}

will result in an error Error: useState only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component

Based on another SO question related to server actions (here) I thought I could use cookies to communicate the error to /products and then render a client component that uses the toast but ran into issues because I can trigger these server actions only from a client component.

How should I approach this? Is toast just the wrong type of component here or is there a better way to do this?

2
  • To me this seems more like an UI question than a coding question, perhaps more suitable for User Experience Stack Exchange rather than here. A coding question may be more appropriate once you've settled for the desired behavior. Commented Feb 20, 2024 at 14:42
  • @Alejandro thanks, I tried re-phrasing the question, is it more clear now? Commented Feb 20, 2024 at 15:43

1 Answer 1

1

My understanding is the toast packages are meant for client side. For server side, I think you can create a loading.tsx page and nextjs will show the loading page then the intended page. If it’s a client side component inside a server rendered page, you should be able to use React Suspense to wrap the client side component in your server rendered page

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, toasts can only be shown in Client Components. robinwieruch.de/react-server-actions-toast

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.