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

React:在传递给类构造函数的回调函数中使用状态不会使用最新版本的状态[duplicate]

黄扬
2023-03-14

很抱歉,标题令人困惑,但下面是发生的情况:

MyComponent中,我正在使用useStateReact钩子设置count状态。一旦组件挂载(即没有依赖项的useffect),我将实例化两个MyClass对象,其中第一个参数作为一个回调函数来递增状态,第二个参数是调用回调函数的超时时间。

MyClass的第一个实例在1000毫秒内调用回调,并为count设置新值,该值一旦更新,将记录在第二个useffect中。

但是,当MyClass的第二个实例调用回调(在timeOut3000毫秒之后),并尝试增加count值时,它使用了MyClass实例化时的count状态(该状态为0),因此它将count增加到1(想要的行为是增加到2,因为MyClass的第一个实例已经从0增加到1)

这与setState的异步行为无关,因为很明显,对count的第一次更新发生在第二个实例再次尝试更新之前(第二个useffect在更新count状态时被调用,您可以从控制台日志消息中看到,在第二个MyClass实例调用回调之前,会调用第二个useffect)。

JSIDLE链接:https://jsfiddle.net/hfv24dpL/

总之,我认为问题在于回调函数中的count状态是回调函数传递给MyClass构造函数count状态的副本。

这个例子的一个解决方案可以是在更新Count状态时(在第二个use效应中)实例化MyClass的第二个实例,但这不是我要找的解决方案。

另一种解决方案是使用setCount(prevCount=

我希望能够在组件装载时(在firstuseEffect中)实例化类,并使回调引用最新版本的count

是否有解决方案^或者没有办法绕过此javascript和React实现?感谢您阅读所有这些,我知道它很长:)

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

class MyClass{

  constructor(callback, timeOut){

    // call callback in timeOut milliseconds
    this.timeOutId = setTimeout(() => {
      callback();

      }, timeOut)

  }

  clearTimeOut(){

    clearTimeout(this.timeOutId);

  }

}


function MyComponent(){

  var [count, setCount] = useState(0);

  // component did mount
  useEffect(() => {
    let myClass1 = new MyClass(funcToCallback, 1000);
    let myClass2 = new MyClass(funcToCallback, 3000);

    // when component unmounts, clear the timeouts of MyClass instances
    return () => {

      myClass1.clearTimeOut();
      myClass2.clearTimeOut();

    }
  }, []);


  // counter state updated
  useEffect(() => {

    console.log("COUNT UPDATED TO: ", count);

  }, [count])

  // get counter and increment it by 1
  function funcToCallback(){

    console.log("CALLBACK CALLED");
    let newCount = count + 1;
    incCount(newCount);

  }

  function incCount(newCount){

    console.log("NEW COUNT: ", newCount);
    setCount(newCount);

  }

  return (
    <div>
      COUNT: { count }
    </div>
  )

}

共有1个答案

包和泰
2023-03-14

count为0时,使用的funcToCallback是组件初始装载中的一个。使用const声明的变量不会更改,useffect回调只调用一次,funcToCallback关闭的count永远保持为0。

最简单的修复方法是改用setter的函数版本,它会将先前的状态作为参数提供给您,然后您可以增加它。改变

  function incCount(newCount){
    console.log("NEW COUNT: ", newCount);
    setCount(newCount);
  }

  function incCount(){
    setCount((lastCount) => {
      console.log("NEW COUNT: ", (lastCount + 1));
      return lastCount + 1;
    });
  }
 类似资料:
  • 但是控制台显示一个错误: 未捕获的 DOMException:无法在 “History” 上执行 'pushState':无法克隆 Symbol(react.element)。 这是什么意思?对此我能做些什么?

  • 问题内容: 我的工厂如下 这是Foo的定义: 好。我不确定如何使用Guice将此参数传递给Foo构造函数? 有任何想法吗? 问题答案: 所有“ Guice构造函数参数”答案在某种程度上似乎都不完整。这是一个完整的解决方案,包括用法: //在实现类上注释构造函数和辅助参数 //使用仅接受辅助参数的create()方法创建工厂接口。 // FooFactory接口没有显式的实现类(Guice Magi

  • 我的Navbar组件有2个子组件。每个组件都有自己的状态。在其组成部分内工作正常的国家。如何更新这两个状态从假到真的同时,当两个功能onclick将被执行? 主组件导航栏 列表菜单组件 汉堡包成分

  • 当我们在ReactJS状态上存储函数时,我在这里遇到了一些非常奇怪的事情。 我用钩子创建了一个react状态,其中包含: 数字变量 回调函数 由于钩子本身在setState期间没有回调,所以我使用此方法在状态更改后的useEffect期间切换回调。 我在setState期间传递的回调是打印state.number和secondNumber值的值。设置状态完成后,state.number的值应为4,

  • 我试图做一个登录表单,它需要我迁移我的soloreac应用程序在反应redux应用程序。我面临许多错误,并坚持与。我是这方面的新手,任何帮助都会得到重视。 指数js文件 应用程序。js文件: 我得到这个错误。我不明白是什么文件或代码导致了这个错误。 类型错误:存储。getState不是新提供程序节点的函数\u modules/react redux/es/components/Provider。j

  • 这两个是等价的吗?如果不是,哪一个是最好的,为什么?