Javascript onClick内的反应状态引用错误-可能存在关闭问题?

Javascript onClick内的反应状态引用错误-可能存在关闭问题?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,这里是我拥有的React组件的精简版本。它是一个带有介绍动画的主屏幕,在超时后将自动结束并淡出,但用户也可以跳过 import React, { useEffect, useState } from "react"; export function Home() { const [introEnded, setIntroEnded] = useState(false); // function to end intro animation function endIntro()

这里是我拥有的React组件的精简版本。它是一个带有介绍动画的主屏幕,在超时后将自动结束并淡出,但用户也可以跳过

import React, { useEffect, useState } from "react";

export function Home() {
  const [introEnded, setIntroEnded] = useState(false);

  // function to end intro animation
  function endIntro() {
    console.log(introEnded); // THIS IS WRONG THE SECOND TIME FUNCTION IS CALLED
    if (!introEnded) {
      setIntroEnded(true);
      // do various other stuff
    }
    // do various other stuff
  }

  // if user does not interact, intro ends automatically
  useEffect(() => {
    setTimeout(function() {
      endIntro();
    }, 4000);
  }, []);

  // user can skip intro on click
  return (
    <div>
      <div onClick={endIntro}>Skip Intro</div>
    </div>
  );
}
import React,{useffect,useState}来自“React”;
导出函数Home(){
常量[introEnded,setIntroEnded]=useState(false);
//结束介绍动画的函数
函数endIntro(){
console.log(introend);//第二次调用函数时,这是错误的
如果(!内向){
设置为内向(真);
//做各种其他的事情
}
//做各种其他的事情
}
//如果用户不进行交互,介绍将自动结束
useffect(()=>{
setTimeout(函数(){
endIntro();
}, 4000);
}, []);
//用户可以单击跳过介绍
返回(
跳过简介
);
}
问题是,在用户跳过后,当超时开始并再次调用
endIntro()
时,
introend
状态是错误的。第一次调用
endIntro()
时,我已将其明确设置为true,但第二次调用
endIntro()
时似乎引用了旧的状态

研究告诉我这是一个封闭的问题,但我无法找到解决办法


发生了什么事,我该怎么解决?谢谢

是的,这是一个Javascript关闭问题。调用useEffect时,变量introEnded的值为false,这是无法避免的。为了实现这个目标,我们需要编写一些如下的手动代码

导出函数Home(){
常量[introEnded,setIntroEnded]=useState(false);
const[appeased,setappeased]=useState(0);
const start=React.useMoom(()=>{
返回新日期().getTime();
}, []);
//结束介绍动画的函数
const endIntro=React.useCallback(()=>{
console.log(introend);//第二次调用函数时,这是错误的
如果(!内向){
设置为内向(真);
//做各种其他的事情
}
//做各种其他的事情
},[内向];
//如果用户不进行交互,介绍将自动结束
useffect(()=>{
//控制台日志(已用);
设timerId=-1
如果(4000>已过){
timerId=setTimeout(函数(){
endIntro();
},4000-年;
}
return()=>{
setAppeased(新日期().getTime()-start);
如果(timerId>0)clearTimeout(timerId);
};
},[经过,结束,开始];
//用户可以单击跳过介绍
返回(
跳过简介
);

}
您不必在
useffect
中调用整个函数,只需更新您的简介
状态即可

此外,您可能需要返回一个清理函数,该函数将在
useffect
结束时将
状态重置为
false
,该函数将模拟
组件willunmount()
。在这里阅读更多

const-App=()=>{
常量[introEnded,setIntroEnded]=React.useState(false);
//结束介绍动画的函数
函数endIntro(){
setIntroEnded(真)
//做你的其他事情
console.log('跳过')
}
//如果用户不进行交互,介绍将自动结束
React.useffect(()=>{
//在x秒后改变状态
setTimeout(函数(){
setIntroEnded(真)
}, 4000);
//清理并将其设置回false
return()=>setIntroEnded(false)
}, []);
返回(
跳过简介
{!简介?你的简介…这将在4秒后结束..:简介已结束..}
)
}
ReactDOM.render(,document.getElementById('root'))

您必须在代码中实现的一些技巧:

  • 主组件销毁时,通过返回的id清除超时
  • 改为使用setState回调,并在将函数调用为setTimeout回调之前进行检查
  • import React,{useffect,useState}来自“React”;
    导出函数Home(){
    常量[introEnded,setIntroEnded]=useState(false);
    //结束介绍动画的函数
    函数endIntro(){
    console.log(introend);//第二次调用函数时,这是错误的
    setIntroEnded(()=>true);
    //做各种其他的事情
    //做各种其他的事情
    }
    //如果用户不进行交互,介绍将自动结束
    useffect(()=>{
    const setTimeoutId=setTimeout(()=>{
    如果(!内向){
    endIntro();
    }
    }, 4000);
    return()=>{
    clearTimeout(setTimeoutId);
    };
    }, []);
    //用户可以单击跳过介绍
    返回(
    endIntro()}>跳过介绍
    );
    
    }
    因此,我将得出结论,当应用程序加载时,您调用动画,以便它现在开始动画用户单击skip,但动画仍然有效,因此您需要取消正在进行的动画,该动画将在4秒内结束。这是您的问题吗?这是您正在寻找的吗?