You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 08:45:25