Problems with the duration of Shadcn Toasts (Inspired by the react-hot-toast library)

Within a 13.4 Nextjs project (app router), utilizing Typescript and TailwindCSS.

I am currently exploring the usage of toasts provided by the remarkable shadcnUI Library, which draws inspiration from react-hot-toast while adding its own unique flair.

Implementing the toast's core functionalities posed no issues for me initially. However, things took a turn when I attempted to include a timer bar at the bottom of each toast to display the duration of the toast.

I was able to successfully display the timer bar (a customized progress bar element) and synchronize it with the duration of each toast.

During this process, I noticed that the actual duration of the toast did not align with the props I assigned to it or the value designated in the TOAST_REMOVE_DELAY constant within the use-toast.ts file of the shadcn component.

I experimented with various configurations, only to discover that the Toaster had a default duration of 5000ms (5s), set by the root toaster inherited from react-hot-toast. Surprisingly, the "duration" value provided as props within the individual Toast component did not override this default setting.

After tinkering with the code extensively, I struggled to pass the duration prop effectively and make it the sole determinant of the toast's duration (excluding null values, where the default value is applied).

To anyone willing to offer assistance...

Here is the use toast:

import * as React from "react"

import type {
  ToastActionElement,
  ToastProps,
} from "@/components/ui/toast"

const TOAST_LIMIT = 3
export const TOAST_REMOVE_DELAY = 2000

type ToasterToast = ToastProps & {
  id: string
  title?: React.ReactNode
  description?: React.ReactNode
  action?: ToastActionElement
  duration?: number
}
...

Here is the Toaster:

/** @format */

'use client';

import {
  Toast,
  ToastClose,
  ToastDescription,
  ToastProvider,
  ToastTitle,
  ToastViewport,
} from '@/components/ui/toast';
import { useToast } from '@/components/ui/use-toast';
import { TimerBar } from '@/components/ui/timerBar';
import { TOAST_REMOVE_DELAY } from '@/components/ui/use-toast';
...

Here is the Toast (not crucial but valuable for replication):

/** @format */

import * as React from 'react';
import * as ToastPrimitives from '@radix-ui/react-toast';
import { cva, type VariantProps } from 'class-variance-authority';
import { Icon } from '@/components/icons/icons';
import { cn } from '@/lib/helpers/utils';
...

<p>I've explored different options:</p>
<ul>
<li>Directly modifying the TOAST_REMOVE_DELAY constant (to no avail)</li>
<li>Incorporating an additional timer within the setTimeout function of addToRemoveQueue</li>
</ul>
<pre><code>const addToRemoveQueue = (toastId: string, delay: number) => {
  if (toastTimeouts.has(toastId)) {
    return
  }
...

It seems even the default TOAST_REMOVE_DELAY does not impact the toast duration. Although set to 1000000, the toasts persist for only 5000 milliseconds each.

  • I attempted to introduce another timer triggering the DISMISS_TOAST action, yet it only functions for durations shorter than 5 seconds. Beyond that, the Toaster's built-in timer overrides the custom setup.

  • Considering whether this issue may be specific to Development Mode, I deployed the solution into production with similar outcomes.

Answer №1

It seems that I overlooked passing the prop duration in the Toaster component:

export function Toaster() {
  const { toasts } = useToast();

  return (
    <div className="absolute max-w-full">
<ToastProvider
      duration={TOAST_REMOVE_DELAY}>
        {toasts.map(function ({
          id,
          title,
          description,
          action,
          duration,
          ...props
        }) {
          return (
            <Toast key={id} **duration={duration}** {...props}>
              <div className="flex flex-col w-full">
                <div className="flex justify-start items-center w-full p-2 gap-2 mr-4">
                  <div className="grid gap-1">
                    {title && <ToastTitle>{title}</ToastTitle>}
                    {description && (
                      <ToastDescription>{description}</ToastDescription>
                    )}
                  </div>
                  {action}
                </div>
                <ToastClose />
                <TimerBar max={duration || TOAST_REMOVE_DELAY} />
              </div>
            </Toast>
          );
        })}
        <ToastViewport />
      </ToastProvider>
    </div>
  );
}

If you're interested, here are the corrected files: use-toast:

// Code inspired by react-hot-toast library
import * as React from "react"
import type {
  ToastActionElement,
  ToastProps,
} from "@/components/ui/toast"

const TOAST_LIMIT = 3
export const TOAST_REMOVE_DELAY = 3000

type ToasterToast = ToastProps & {
  id: string
  title?: React.ReactNode
  description?: React.ReactNode
  action?: ToastActionElement
  duration?: number
}

// Rest of the script contains details about toast actions and reducers but has been omitted for brevity.

To test it out, add the Toaster within ToastProvider in your RootLayout:

return (
    <NextAuthSessionProvider session={session}>
      <html lang="en">
        <body
          className={`${circularBold.variable} ${gambettaReg.variable} ${gambettaSemi.variable} ${nunito.variable} ${inter.variable} font-inter`}
        >
          <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
            <main className="flex flex-col justify-between items-center min-h-screen min-w-screen">
              <Header user={session?.user} />
              {children}
              <Footer />
              **<Toaster />**
            </main>
          </ThemeProvider>
        </body>
      </html>
    </NextAuthSessionProvider>
  );
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to update an Array<Object> State in ReactJS without causing mutation

In my program, I store an array of objects containing meta information. This is the format for each object. this.state.slotData [{ availability: boolean, id: number, car: { RegistrationNumber : string, ...

SvgIcon is not a recognized element within the JSX syntax

Encountering a frustrating TypeScript error in an Electron React App, using MUI and MUI Icons. Although it's not halting the build process, I'm determined to resolve it as it's causing issues with defining props for icons. In a previous pro ...

Date selection feature in Material UI causing application malfunction when using defaultValue attribute with Typescript

Recently, I discovered the amazing functionality of the Material UI library and decided to try out their date pickers. Everything seemed fine at first, but now I'm facing an issue that has left me puzzled. Below is a snippet of my code (which closely ...

Sustaining component state in NextJS applications

I am facing an issue with my NextJS app where I have two distinct layouts for landscape and portrait modes. The parent page structure is as follows: <NavWrapper> <MyPage> </NavWrapper> The NavWrapper component handles the layout based on ...

Type of event triggered by user file upload via INPUT element

I have a piece of code that reads the contents of a locally stored file. Here is what it looks like: onFile(event: any) { console.log(event); const file = event.target.files[0]; const reader = new FileReader(); reader.onloadend = (ev: any) => { ...

What is the best way to create a higher order component (HOC) for securing routes when utilizing an httpOnly cookie in

I have implemented a method of storing my token in a httpOnly cookie, but I ran into an issue when trying to create a Higher Order Component (HOC) for route protection. It seems that there is no direct way to access the cookie inside a component; instead ...

Error: Trying to modify an immutable property 'title' of object '#<Object>' - React JS and Typescript

Whenever I press the Add button, all input values are stored in a reducer. However, if I append any character to the existing value in the input fields, it triggers the following error: Cannot assign to read only property 'title' of object &apos ...

Angular's FormGroup for reactive forms is a powerful feature that allows for

Why am I unable to type in the input field before setting a value? html <form action="" [formGroup]="titleForm"> <input class="note-title" type="text" formControlName="title"> </form> ...

The HttpClient.get('/') request with {observe: 'response'} is failing to retrieve some headers

Currently, I'm in the process of writing an API GET request by utilizing HttpClient.get(). Upon passing in the option to observe the response, I've encountered an issue where accessing the .keys() does not provide me with any headers apart from C ...

The Angular Material date picker unpredictably updates when a date is manually changed and the tab key is pressed

My component involves the use of the Angular material date picker. However, I have encountered a strange issue with it. When I select a date using the calendar control, everything works fine. But if I manually change the date and then press the tab button, ...

Organize items within an array based on dual properties rather than a single one

Here is an array of objects that I would like to group based on certain keys (JSON format): [ { "name": "john", "lastName": "doe", "gender": "male" }, { "name": &qu ...

The occurrence of a loading error arises when attempting to load the second component, displaying the message 'The template instructed for component SidebarComponent is

My journey with Angular has just begun, and I decided to challenge myself by creating a simplistic dashboard. In order to achieve this, I developed two components called DashboardComponent and SidebarComponent. The DashboardComponent loads smoothly witho ...

Looking for a method to efficiently populate an array with values in Typescript

Here is an example of how I work with arrays in my code: var alphas: string[]; alphas = ['abc1', 'abc2', 'abc3']; // (this array can be changed) My modal class looks like this: export class Team { TeamName: string; } To ...

Is there a way to trigger a dialog to open upon clicking on a particular date?

Currently, I am working on developing a scheduling application. My goal is to create a feature where clicking on a specific date will open a dialog box. To accomplish this, I am utilizing the ShadCN Date-picker. calendar-picker.tsx "use client" ...

retrieve the checkbox formgroup using the Response API

After following a tutorial on creating dynamic checkboxes, I now need to implement dynamic checkboxes using an API request. In my implementation so far, I have defined the structure as shown below: inquiry-response.ts interface Item { // Item interface ...

Jest identifies active handles when executing synchronous scrypt operations in the crypto module of Node.js

During the execution of a unit test using the scryptSync function from the crypto package, I am encountering error messages and warnings that are unfamiliar to me. For instance, here is an example of a unit test I am running in Jest: it('Should match ...

Issue with Angular 2 Custom Pipe not Refreshing Unless Object is Saved

I recently created a custom Angular 2 pipe that formats a phone number from a 10-digit string to 'XXX-XXX-XXXX'. The pipe is functioning perfectly, but the issue arises when it fails to update in real-time during keypress; instead, it updates onl ...

Stop committing changes in Git when there are any TypeScript errors found

While working on my project in TypeScript using Visual Code, I encountered a situation where I was able to commit and push my changes to the server through Git (Azure) even though there was an error in my code causing a build failure. It made me wonder i ...

ESLint is reminding you that the `parserOptions.project` setting must be configured to reference the tsconfig.json files specific to your

Within my NX Workspace, I am developing a NestJS-Angular project. Upon running nx lint, an error is triggered with the following message: Error: A lint rule requiring the TypeScript type-checker to be fully available has been attempted, but `parserOptions. ...

Setting up Emotion js in a React TypeScript project using Vite 4

Currently, I am in the process of transitioning from Webpack to Vite for my React Typescript application. I have been attempting to integrate Emotion js into the project. "@vitejs/plugin-react": "^4.0.1", "vite": "^4.3.9 ...