我正在 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} />
</>
)
}
您面临的问题源于这样一个事实:每次单击按钮时,都会设置一个新的超时,而不会清除前一个超时。这会导致意外的行为,尤其是在发生快速点击时。为了解决这个问题,您可以使用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 将其清除。这可确保在任何给定时间只有一个超时处于活动状态,从而防止您因快速单击按钮而遇到不稳定的行为。