当前位置: 首页 > 知识库问答 >
问题:

“setInterval”内的函数不从钩子接收更新的变量

吴开宇
2023-03-14

在useEffect钩子中,我设置了间隔,这是运行函数“calculateCircle”。在那里我做了一些逻辑,包括设置状态(使用useState钩子)。钩子中的变量会被更新,我会在页面上呈现并看到它们,但这个函数会保持对旧值的控制台登录。

我将我的组件更改为基于类的组件(没有挂钩),现在一切正常。但是我想知道使用钩子的问题是什么。

const Features = () => {
 const block1 = React.createRef();
 const shadowText = React.createRef();

 const [ mouseIn, setMouseIn ] = useState(false);
 const [ xCircle, setXCircle] = useState(-50);

 const calculateCircle = () => {
    console.log('mouseIn :', mouseIn); //never changes, but in page - yes

    if (!mouseIn) {  //never skips this loop
        console.log('begin', xCircle);//always the same            
        let r = 50;
        let yCircle = Math.sqrt(r*r - xCircle*xCircle);
        if (shadowText.current) draw(xCircle, yCircle);
        setXCircle(prev => {
            console.log('xCircle:', prev);
            return prev > 50 ? -50 : prev + 1
        });            
        console.log('end', xCircle, yCircle);
    }            
} //on page I see that xCircle changes correctly

useEffect(() => {
    const cycle = setInterval(() => calculateCircle(), 1000);
    return () => {
        clearInterval(cycle);
    }
}, []);

//没有钩子,它就能工作;

共有1个答案

闻人宇定
2023-03-14

由于calculateCircle实例最初仅从useEffect钩子中引用,因此它从创建此函数时的闭包中获取xCircle和mouseIn值,该函数的setInterval处于初始调用状态。

您需要将第二个参数传递给useffect,以便在xCircle或mouseIn更改时再次创建此方法

const Features = () => {
 const block1 = React.createRef();
 const shadowText = React.createRef();

 const [ mouseIn, setMouseIn ] = useState(false);
 const [ xCircle, setXCircle] = useState(-50);

 const calculateCircle = () => {
    console.log('mouseIn :', mouseIn); //never changes, but in page - yes

    if (!mouseIn) {  //never skips this loop
        console.log('begin', xCircle);//always the same            
        let r = 50;
        let yCircle = Math.sqrt(r*r - xCircle*xCircle);
        if (shadowText.current) draw(xCircle, yCircle);
        setXCircle(prev => {
            console.log('xCircle:', prev);
            return prev > 50 ? -50 : prev + 1
        });            
        console.log('end', xCircle, yCircle);
    }            
} //on page I see that xCircle changes correctly

useEffect(() => {
    const cycle = setInterval(() => calculateCircle(), 1000);
    return () => {
        clearInterval(cycle);
    }
}, [mouseIn, xCircle]);
 类似资料:
  • 我正在构建一个制表符视图,我不明白为什么useState钩子没有更新我的状态。我肯定这是件容易的事,但我在这里已经被难住了一段时间... 我可以看到onPress函数已启动,如果我注销,则item.label是正确的。但是,即使我硬编码参数,setState也不会更改。

  • 其默认“BDD”式接口,mocha提供钩before(),after(),beforeEach(),和afterEach()。这些应该用于设置前置条件并在测试后进行清理。 describe('hooks', function() { before(function() { // runs before all tests in this block }); after(function() {

  • 我正在试用新的反应挂钩,并有一个时钟组件,计数器应该每秒钟增加一次。但是,该值不增加超过1。

  • 问题内容: 是否有一种方法可以在每次从服务器返回响应后都调用一个函数,而无需在回调之后显式调用它? 主要目的是,我确实有一个通用的错误处理程序服务,可以在每个请求的回调中调用该服务,并且希望在某处指定该服务,然后该服务将自动被调用。 问题答案: 我为Gloopy提供了+1的解决方案,但是,他所引用的其他文章在配置和拦截器中定义的函数中进行了DOM操作。相反,我将启动微调器的逻辑移到了拦截器的顶部,

  • App.js中有一个全局变量,该变量在我的应用程序组件之外设置。 它监视棋盘游戏正在进行的移动。在黑板下面是一些导航按钮。如果您单击

  • 我的应用程序使用MVVM架构。我有一个活动及其子片段共享的ViewModel。ViewModel包含一个简单的字符串,我想从活动中更新它,并在片段中观察它。 我的问题很简单:LiveData更新后,我的片段中永远不会到达observe回调。为了进行测试,我尝试在中观察数据,但效果很好。此外,在我在其他ViewModels中声明的片段中观察LiveData变量也可以很好地工作。奇怪的是,只有这个Vi