Next.js 13.4中shadcnUI Toast自定义duration不生效问题求助
解决方案:shadcnUI Toast 自定义 duration 不生效问题
1. 核心问题定位
进度条动画时长、Toast 移除定时器都硬绑定了全局默认的 5000ms,没有读取每个 Toast 实例传入的自定义 duration 值,导致自定义时长失效。
2. 具体修复步骤
(1)修正 use-toast.ts 中的 Toast 创建逻辑
确保每个 Toast 实例存储自定义的 duration,并在移除队列中使用该值:
// use-toast.ts import { useState, useCallback } from 'react' import type { Toast, ToastProps } from './toast' const TOAST_REMOVE_DELAY = 5000 // 保留默认值,但不再强制全局使用 export function useToast() { const [toasts, setToasts] = useState<Toast[]>([]) const createToast = useCallback((props: ToastProps) => { const id = crypto.randomUUID() // 优先使用传入的 duration,否则用默认值 const toast: Toast = { id, duration: props.duration ?? TOAST_REMOVE_DELAY, ...props, } setToasts(prev => [...prev, toast]) addToRemoveQueue(id) return id }, []) const addToRemoveQueue = useCallback((toastId: string) => { const targetToast = toasts.find(t => t.id === toastId) if (!targetToast) return // 使用当前 Toast 实例的 duration 而非全局常量 setTimeout(() => { removeToast(toastId) }, targetToast.duration) }, [toasts]) const removeToast = useCallback((toastId: string) => { setToasts(prev => prev.filter(t => t.id !== toastId)) }, []) return { toast: createToast, removeToast, toasts, } }
(2)修改 Toast 组件的进度条动画绑定
让进度条的过渡时长与当前 Toast 的 duration 同步:
// toast.tsx import { useEffect, useRef } from 'react' import type { Toast } from './use-toast' interface ToastProps { toast: Toast onClose: () => void } export function Toast({ toast, onClose }: ToastProps) { const progressRef = useRef<HTMLDivElement>(null) useEffect(() => { if (!progressRef.current) return // 启动进度条动画,使用当前 Toast 的 duration progressRef.current.style.transition = `width ${toast.duration}ms linear` progressRef.current.style.width = '0%' }, [toast.id, toast.duration]) return ( <div className="group relative flex w-full items-center justify-between gap-2 rounded-md bg-slate-800 px-4 py-3 text-white"> <div className="flex items-center gap-2"> <span className="font-medium">{toast.title}</span> {toast.description && <span className="text-sm text-slate-300">{toast.description}</span>} </div> <button onClick={onClose} className="text-slate-400 hover:text-white"> × </button> {/* 进度条 */} <div ref={progressRef} className="absolute bottom-0 left-0 h-0.5 bg-white/50" style={{ width: '100%', transformOrigin: 'left' }} /> </div> ) }
(3)调用时传入自定义 duration
确保调用 Toast 时正确传递参数:
// 示例调用 import { useToast } from '@/components/ui/use-toast' function Demo() { const { toast } = useToast() const handleShowToast = () => { toast({ title: '操作成功', description: '内容已保存', duration: 3000 // 自定义3秒时长 }) } return <button onClick={handleShowToast}>显示Toast</button> }
3. 验证修复
- 本地开发环境测试不同 duration 值,确认进度条动画时长与 Toast 消失时长一致
- 生产环境构建后验证,确保自定义时长逻辑正常生效
内容的提问来源于stack exchange,提问作者Samuel Amann
相关产品推荐
相关产品推荐

