Javascript 使用Hooks-won';在React中设置单击事件的间隔;不要使用更新的状态值
我试图创建一个过滤器下拉菜单,如果用户没有手动关闭它,并且在1秒后将鼠标移离过滤器,它会隐藏自己 问题是Javascript 使用Hooks-won';在React中设置单击事件的间隔;不要使用更新的状态值,javascript,reactjs,typescript,state,setinterval,Javascript,Reactjs,Typescript,State,Setinterval,我试图创建一个过滤器下拉菜单,如果用户没有手动关闭它,并且在1秒后将鼠标移离过滤器,它会隐藏自己 问题是mouseInside布尔状态在间隔内从未更改为false。我相信这是因为react组件得到了重新渲染,但并不完全确定 我不知道如何修复它,也不知道如何错误地使用状态变量和局部变量 我在React with hooks中使用了TypeScript: const Filter: React.FC = () => { const [shown, setShown] = useState&
mouseInside
布尔状态在间隔内从未更改为false
。我相信这是因为react组件得到了重新渲染,但并不完全确定
我不知道如何修复它,也不知道如何错误地使用状态变量和局部变量
我在React with hooks中使用了TypeScript:
const Filter: React.FC = () => {
const [shown, setShown] = useState<boolean>(false);
const [mouseInside, setMouseInside] = useState<boolean>(false);
let interval: NodeJS.Timeout | null = null;
const handleToggle = () => {
setShown(!shown);
interval = setInterval(() => {
console.log(mouseInside);
// mouseInside is permanently true
if (!mouseInside && interval) {
// this never gets triggered
clearInterval(interval);
setShown(false);
console.log("Finished!");
}
}, 1000);
}
};
return (
<div
style={{ width: 100, height: 100, backgroundColor: "lightgray" }}
onClick={handleToggle}
onMouseEnter={() => setMouseInside(true)}
onMouseLeave={() => setMouseInside(false)}
>
<p>Click me!</p>
{shown && <div>drop down here...</dv>}
</div>
);
};
const过滤器:React.FC=()=>{
常量[显示,设置显示]=使用状态(假);
const[mouseInside,setMouseInside]=useState(false);
let interval:NodeJS.Timeout | null=null;
const handleToggle=()=>{
设置显示(!如图所示);
间隔=设置间隔(()=>{
控制台日志(鼠标侧);
//mouseInside永远是正确的
if(!mouseInside&&interval){
//这永远不会被触发
间隔时间;
设置显示(假);
console.log(“完成!”);
}
}, 1000);
}
};
返回(
setMouseInside(真)}
onMouseLeave={()=>setMouseInside(false)}
>
点击我
{显示并在此处下拉…}
);
};
当用户离开过滤框时,我需要mouseInside最终更改为false。肯定会触发onMouseLeave
事件,但我认为这是导致问题的原因
也许我需要使用useffect
?我不知道如何将其与setInterval
一起使用的最佳方法。为了“订阅”回调函数以更改状态,您完全可以使用useffect
挂钩:
函数自动调用ThestMouseOutside(){
设置超时(()=>{
如果(鼠标侧){
setMouseInside(假);
}
}, 1000);
}
useEffect(自动在鼠标外[mouseInside]);
useffect
的第二个参数订阅automaticallySetMouseOutside
,以便在更改mouseInside
时被调用
虽然此代码旨在举例说明此钩子的使用,它并不准确-因为它可以在用户还在里面时关闭菜单。如果您想要问题的完整解决方案,请检查此项。在
handleToggle
中声明interval action时,它位于自己的范围内,与实际状态没有绑定
const handleInterval = interval => {
console.log(mouseInside);
if (!mouseInside && interval) {
// this never gets triggered
clearInterval(interval);
setShown(false);
console.log("Finished!");
}
}
const handleToggle = () => {
interval = setInterval(() => {
() => handleInterval(interval),
}, 1000);
}
};
我最终使用了@GalAbra建议的部分内容,但我只想在用户单击切换器时创建间隔,并且仅在菜单打开时:
const [shown, setShown] = useState<boolean>(false);
const [mouseInside, setMouseInside] = useState<boolean>(false);
useEffect(() => {
let interval: NodeJS.Timeout | null;
if (shown) {
interval = setInterval(() => {
if (!mouseInside && interval) {
setShown(false);
}
}, 500);
}
return () => {
if (interval) clearInterval(interval);
};
}, [shown, mouseInside]);
return (
<div
style={{ width: 100, height: 100, backgroundColor: "lightgray" }}
onClick={() => setShown(!shown)}
onMouseEnter={() => setMouseInside(true)}
onMouseLeave={() => setMouseInside(false)}
>
<p>Click me!</p>
{shown && <div>drop down here...</dv>}
</div>
);
const[显示,设置显示]=使用状态(false);
const[mouseInside,setMouseInside]=useState(false);
useffect(()=>{
let interval:NodeJS.Timeout | null;
如图所示{
间隔=设置间隔(()=>{
if(!mouseInside&&interval){
设置显示(假);
}
}, 500);
}
return()=>{
if(间隔)clearInterval(间隔);
};
},[如图所示,鼠标指针];
返回(
设置显示(!显示)}
onMouseCenter={()=>setMouseInside(true)}
onMouseLeave={()=>setMouseInside(false)}
>
单击我!
{显示并在此处下拉…}
);
您在哪里使用handleToggle
?@GalAbra抱歉。我忘了把它包括在样品里。刚刚加的,谢谢。我让它工作了。我必须像你建议的那样使用effect,并且只有当用户单击下拉列表时才能创建间隔。我不得不稍微修改一下。很高兴听到这个消息!通常情况下,这是比较可取的,因为它会导致性能问题。是的,这是我最关心的问题。我在网上找到的大多数示例都依赖于始终运行的间隔,但我只希望在打开菜单以避免性能问题时运行它。我发布了我的更新版本,因为它确实与您的示例有很大不同,但您给了我正确的方向:)谢谢您的建议。我最终使用useEffect来确保对间隔的引用相同。请注意,由于您在效果中声明了让间隔
,因此每次输入效果时,您都会声明新的间隔
。。。考虑使用<代码>让间隔= USERF(NULL)< /代码>外部效果,并分配或清除<代码>间隔。当前< /代码>谢谢。我更新了我的解决方案。我认为使用interval.current=setInterval
仍然意味着每次输入效果时我都会创建一个新的间隔?我必须在没有useRef的情况下编辑回答案,因为这会导致在每个选项卡上呈现组件时打开多个选项卡的问题。很奇怪。