Next.js 13客户端组件状态不更新:点击按钮无法打开弹窗
问题:Next.js 13 App目录中点击按钮无法打开弹窗
在Next.js 13实验性App目录下,点击按钮尝试打开弹窗时,状态isDialogOpen始终为false,弹窗无法正常显示。相关代码如下:
index.js
'use client'; export default function Test() { const [ isDialogOpen, setIsDialogOpen ] = useState(false); return ( <> <ButtonComponent className={'flex items-center group'} onButtonClick={() => { setIsDialogOpen(true);}} type={ButtonType.SECONDARY} > <Resume className={'mr-2 duration-300 group-hover:stroke-white-default group-hover:dark:stroke-black-default scale-125 stroke-neongreen-default'} /> <span> Open Dialog </span> </ButtonComponent> <DialogComponent open={isDialogOpen} setIsOpen={setIsDialogOpen} title={'Dialog open'} > <p>Hi, this is dialog</p> </DialogComponent> </> ); }
dialog.js
'use client'; export default function DialogComponent(props: DialogProps) { const { children = null, open = false, title, setIsOpen } = props; return ( <div className={'flex data-[open=false]:hidden overflow-auto w-full h-screen fixed top-0 left-0 bg-black-default/[.80] z-10 duration-300'} data-open={isOpen} ref={dialogRef} > <div className={'w-full h-screen md:min-h-full md:w-fit min-h-fit m-auto p-4'}> <div className={'flex justify-between items-center'}> <div className={'w-full'}> <h1 className={'text-lg w-fit m-auto block'}>{title}</h1> </div> </div> {children} <div className={'w-full'}> <ButtonComponent className={'m-auto block mt-4'} onButtonClick={() => setIsOpen(false)} type={ButtonType.PRIMARY} > Close </ButtonComponent> </div> </div> </div> ); }
解决方案
1. 修复DialogComponent中data-open的变量错误
DialogComponent的props里接收的是open,但你在data-open属性里用了未定义的isOpen,这会导致弹窗的显示逻辑完全失效。修改如下:
// dialog.js 中修改这一行 data-open={open}
2. 导入缺失的useState
index.js中使用了useState但没有从React导入,这会导致组件报错,添加导入:
// index.js 顶部添加 import { useState } from 'react';
3. 处理未定义的dialogRef
DialogComponent中使用了dialogRef但没有定义,二选一处理:
- 直接去掉
ref={dialogRef}属性(如果不需要这个ref) - 导入
useRef并初始化:
// dialog.js 顶部添加 import { useRef } from 'react'; // 组件内部添加 const dialogRef = useRef(null);
4. 确认ButtonComponent的回调触发逻辑
确保你的ButtonComponent内部正确调用了传入的onButtonClick回调,示例实现如下:
export default function ButtonComponent({ onButtonClick, ...props }) { return ( <button onClick={onButtonClick} {...props}> {props.children} </button> ); }
完成以上修改后,点击按钮应该能正常更新isDialogOpen状态并显示弹窗了。
内容的提问来源于stack exchange,提问作者srth
相关产品推荐
相关产品推荐

