注册新的 onClick 后,保持 React 弹出窗口不消失

问题描述 投票:0回答:1

我正在 React 中创建一个自定义弹出窗口,该弹出窗口在单击按钮后显示,并且我想在 X 秒后离开屏幕。我遇到的问题是,如果您在初始超时结束之前多次单击按钮,您会得到非常奇怪的行为,例如弹出窗口跳进跳出或根本不显示。

我意识到这是由于我滥用 React 状态造成的,但我不知道如何解决这个问题。有人可以帮我吗?

function popupHandler(popupText, setPopupVis, setPopupText) {
    setPopupText(popupText)
    setPopupVis("visible");
    // Works when you click a button ONCE and then don't touch anything during the timeout windows
    // Totally breaks if you do otherwise. 
    // I want to "extend" the timeout so that the 
    //  popup window keeps staying up if the button keeps getting clicked
    setTimeout(() => {
        setPopupVis("hidden")
    }, 3000);
}

function CustomButton({setPopupText, setPopupVis}) {
    return (
        <button onClick={() => popupHandler("Dynamic string", setPopupText, setPopupVis)}>
            I am a button
        </button>
    )
}

function MyPopUp({popupVis, popupText}) {
    return (
        <div style={{visibility: popupVis}}>
            {popupText}
        </div>
    )
}

export default function MyContent() {
    const [popupVis, setPopupVis] = useState('hidden');
    const [popupText, setPopupText] = useState('')
    return (
        <>
            <CustomButton setPopupText={setPopupText} setPopupVis={setPopupVis} />
            <MyPopUp popupVis={popupVis} popupText={popupText} />
        </>
    )
}
reactjs next.js popup timeout react-state
1个回答
0
投票

您面临的问题源于这样一个事实:每次单击按钮时,都会设置一个新的超时,而不会清除前一个超时。这会导致意外的行为,尤其是在发生快速点击时。为了解决这个问题,您可以使用clearTimeout函数清除之前的超时,然后再设置新的超时。以下是您可以修改代码来处理此问题的方法:

import React, { useState } from "react";

function popupHandler(popupText, setPopupVis, setPopupText) {
  setPopupText(popupText);
  setPopupVis("visible");

  // Clear any existing timeout
  if (popupHandler.timerId) {
    clearTimeout(popupHandler.timerId);
  }

  // Set a new timeout
  popupHandler.timerId = setTimeout(() => {
    setPopupVis("hidden");
  }, 3000);
}

function CustomButton({ setPopupText, setPopupVis }) {
  return (
    <button
      onClick={() => popupHandler("Dynamic string", setPopupText, setPopupVis)}
    >
      I am a button
    </button>
  );
}

function MyPopUp({ popupVis, popupText }) {
  return <div style={{ visibility: popupVis }}>{popupText}</div>;
}

export default function MyContent() {
  const [popupVis, setPopupVis] = useState("hidden");
  const [popupText, setPopupText] = useState("");

  return (
    <>
      <CustomButton setPopupText={setPopupText} setPopupVis={setPopupVis} />
      <MyPopUp popupVis={popupVis} popupText={popupText} />
    </>
  );
}

在此修改中,我引入了附加到 popupHandler 函数的timerId 属性来跟踪当前超时。在设置新的超时之前,它会检查是否存在现有超时并使用clearTimeout 将其清除。这可确保在任何给定时间只有一个超时处于活动状态,从而防止您因快速单击按钮而遇到不稳定的行为。

© www.soinside.com 2019 - 2024. All rights reserved.