NextJS14 App Router中Shadcn UI Dialog修改状态时消失问题
问题分析与解决
核心问题1:Dialog因组件重渲染丢失状态
你把SharedDialog定义在ActionMenu组件内部,每次isResultReturned状态变化时,ActionMenu会重新渲染,SharedDialog会被重新创建。Shadcn UI的Dialog内部维护了自己的打开/关闭状态,组件重新创建后这个状态会被重置,所以当你把isResultReturned设为true时,Dialog直接消失了。
核心问题2:状态更新的闭包陷阱
setTimeout里的console.log('check isResultReturned', isResultReturned)拿的是调用deleteNoteGroup时的旧状态值,并不是更新后的新值,所以你看到的日志会误导你以为状态没变化,但实际上setIsResultReturned(true)已经生效了。
修复步骤
- 移除内部嵌套的组件定义
不要在组件内部嵌套定义组件,避免每次渲染都重新创建组件实例。修改后的ActionMenu代码如下:
// app/ActionItem.tsx "use client" import { useState } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { Loader2 } from 'lucide-react'; export default function ActionMenu({ name }: { name: string }) { const [isResultReturned, setIsResultReturned] = useState(true) const deleteNoteGroup= () => { setIsResultReturned(false) setTimeout(() => { console.log('wait for 3 seconds') setIsResultReturned(true) }, 3000) } // 直接渲染Dialog,不再嵌套定义SharedDialog组件 return ( <Dialog> <DialogTrigger asChild> <Button variant="outline">Delete</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Title</DialogTitle> <DialogDescription> Description </DialogDescription> </DialogHeader> <DialogFooter> <Button variant="destructive" onClick={deleteNoteGroup}> {!isResultReturned && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} Delete </Button> </DialogFooter> </DialogContent> </Dialog> ) }
- 解决闭包查看状态的问题(可选)
如果需要在setTimeout里查看最新的isResultReturned状态,可以用useRef同步状态:
// 新增useRef和useEffect const isResultReturnedRef = useRef(isResultReturned); useEffect(() => { isResultReturnedRef.current = isResultReturned; }, [isResultReturned]); // 在setTimeout里查看最新状态 setTimeout(() => { console.log('wait for 3 seconds') setIsResultReturned(true) console.log('check isResultReturned', isResultReturnedRef.current) }, 3000)
这样修改后,Dialog不会在状态更新时消失,状态设置也能正常工作。
内容的提问来源于stack exchange,提问作者richardoey
相关产品推荐
相关产品推荐

