【问题标题】:How to close the dialog on clicking a button using TypeScript and React?如何使用 TypeScript 和 React 关闭单击按钮时的对话框?
【发布时间】:2020-08-13 08:44:07
【问题描述】:

我想通过单击使用 TypeScript 和 React 的按钮来关闭对话框。

我想做的事:

在单击 [click me] 按钮时,isDialogOpen 状态设置为 true,如果 isDialogOpentrue,则会显示对话框。

如果单击此 [单击我] 按钮或用户单击对话框外的任何位置,则该对话框应关闭。

下面是我的代码:

function Parent() {
    const [isDialogOpen, setIsDialogOpen] = React.useState(false);
    return (
        <button onClick={() => setIsDialogOpen(!isDialogOpen)}> click me </button> //on clicking this 
        //button should open the dialog. if dialog open 
        //and clicking this button again should close the dialog
        {isDialogOpen && 
            <Dialog setIsDialogOpen={setIsDialogOpen}/>
        }
    );
}


function Dialog({setIsDialogOpen}: Props) {
    const dialogRef = React.useRef<HTMLDivElement>(null);
    React.useEffect(() => {
        const handleClickOutsideDialog = (event: any) => {
            if (
                dialogRef && dialogRef.current && 
                !dialogRef.current.contains(event.target)
            ) {
                setIsDialogOpen(false);
            }
        };
        document.addEventListener('mousedown', handleClickOutsideDialog);
        return () => {
            document.removeEventListener('mousedown', handleClickOutsideDialog);
        };
    }, [setIsDialogOpen, dialogRef]);
    
    return (
        <Wrapper ref={dialogRef}>
            <Title> title </Title>
            <Description> some big description </Description>
        </Wrapper>
    );
}

它工作正常。但问题是一旦打开对话框然后单击单击我按钮....对话框消失并立即打开。

如果之前打开了对话框,我希望当用户单击单击我按钮时对话框会关闭。

我不知道问题出在哪里。有人可以帮我解决这个问题吗?谢谢。

编辑

下面是我再次尝试添加一个 ref 到按钮单击我的内容。并将其传递给对话框组件以检查 useeffect 方法。

function Parent() {
    const [isDialogOpen, setIsDialogOpen] = React.useState(false);
    const buttonRef = React.useRef<HTMLDivElement>(null);
    const handleClick = () => {
        if (!isDialogOpen) {
            setIsDialogOpen(true);
        }
    };
    return (
        <button onClick={handelClick}> click me </button> //on clicking this 
        //button should open the dialog. if dialog open 
        //and clicking this button again should close the dialog
        {isDialogOpen && 
            <Dialog setIsDialogOpen={setIsDialogOpen} buttonRef={buttonRef}/>
        }
    );
}


function Dialog({setIsDialogOpen, buttonRef}: Props) {
    const dialogRef = React.useRef<HTMLDivElement>(null);
    React.useEffect(() => {
        const handleClickOutsideDialog = (event: any) => {
            if (
                dialogRef && dialogRef.current && 
                !dialogRef.current.contains(event.target) && buttonRef && 
            buttonRef.current && !buttonRef.current.contains(event.target)
            ) {
                setIsDialogOpen(false);
            }
        };
        document.addEventListener('mousedown', handleClickOutsideDialog);
        return () => {
            document.removeEventListener('mousedown', handleClickOutsideDialog);
        };
    }, [setIsDialogOpen, dialogRef]);
    
    return (
        <Wrapper ref={dialogRef}>
            <Title> title </Title>
            <Description> some big description </Description>
        </Wrapper>
    );
}

但是即使用户单击了“单击我”按钮,这也会使对话框保持打开状态。在对话框外部单击将关闭它。

【问题讨论】:

  • 什么是“点击我按钮对话框”?你的意思是“点击我”按钮消失了吗?
  • 不。单击单击我按钮使对话框消失并再次重新打开。
  • 如果没有现场示例很难评估,但请尝试将您的按钮点击处理程序更改为 () =&gt; setIsDialogOpen((open) =&gt; !open)
  • 谢谢,但它是一样的。可能是因为对话框组件中的useeffect。我正在检查点击是否在对话框之外。因此,如果用户单击单击我按钮,则将其计为在对话框外单击,并且 isDialogOpen 设置为 false,然后再次设置为 true,因为单击我按钮 onclick 方法被调用????我怎样才能改变它
  • 你能在这里上传你的 Wrapper 组件吗?

标签: javascript reactjs typescript


【解决方案1】:

接 cmets。

试试 setIsDialogOpen((open) => !open)


你有一个竞争条件。为了美观,你可以使用const onClickClickMe = () =&gt; { if (!isDialogOpen) setIsDialogOpen(true) }; 然后设置onClick={onClickClickMe}

【讨论】:

  • 对其进行了测试。和是一样的。问题是useeffect里面的代码执行第一个设置isDialogOpen为false。然后执行此 onClickClickMe 并将 isDialogOpen 设置为 true。
  • @someuser2491 你能在codeandbox上发布一个小样本吗?
  • 我已经编辑了关于我尝试添加参考以单击我按钮的问题。
  • @someuser2491 当 setDialogOpen 由 handleClickOutsideDialog 设置为 false 时,在 onClickClickMe 重新激活之前需要进行一次完整渲染。在调用 onClickClickMe 之前点击会等待重新渲染是没有意义的。
  • @someuser2491 尝试注释掉 Dialog's useEffectonClickClickMe's if statement 以查看按钮在单击时是否正确关闭对话框。
【解决方案2】:

为什么不直接将 isDialogOpen 状态传递给您的 Dialog 并据此处理切换(显示和隐藏对话框)?比如:

function Parent() {
    const [isDialogOpen, setIsDialogOpen] = React.useState(false)
    const ToggleState = setIsDialogOpen(!isDialogOpen)
    return (
        <>
          <button onClick={ToggleState}>Click me</button>
          <Dialog isOpen={isDialogOpen} />
        </>
    );
}

【讨论】:

    猜你喜欢
    • 2013-04-06
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多