反应setState不更新状态


91

所以我有这个:

let total = newDealersDeckTotal.reduce(function(a, b) {
  return a + b;
},
0);

console.log(total, 'tittal'); //outputs correct total
setTimeout(() => {
  this.setState({dealersOverallTotal: total});
}, 10);

console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1'); //outputs incorrect total

newDealersDeckTotal只是一个数字数组,[1, 5, 9]例如,但是this.state.dealersOverallTotal没有给出正确的总数,但是total呢?我什至设置了超时延迟,以查看是否可以解决问题。任何明显的还是我应该发布更多代码?



@阿桑干杯!!
蠕虫病毒

除了答案中所说的以外,您还要在调用之前显式记录状态的值setState
菲利克斯·克林

1
@FelixKling不我将其设置称为this.state 。我之前记录了一个变量。没有?
蠕虫病毒

由于超时,您setState确实会在登录状态后执行该操作。我认为您打算在调试中执行的操作是将console.log部件置于超时范围之内,而将其置于超时范围之setState内。
法比安·舒尔茨

Answers:


181

setState()通常是异步的,这意味着在您console.log处于状态时,它尚未更新。尝试将日志放入setState()方法的回调中。状态更改完成后执行:

this.setState({ dealersOverallTotal: total }, () => {
  console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
}); 

1
除此之外,OP调用之前显式记录状态值setState
菲利克斯·克林

这也对我有用,过去我使用过:`this.setState({someVar:newValue},function(){console.log(“ force update});',但是由于某种原因,它并不令人担忧还有,当我按照上面描述的那样更新代码时,它起作用了,为什么?
Jozcar

@Jozcar也应该工作,语法不正确(缺少括号):this.setState({someVar: newValue},function(){ console.log("force update") });
Fabian Schultz

imgur.com/Ku0OjTl请告诉我该怎么做才能摆脱这个问题。
约翰西

如果useState在功能组件中使用钩子,则无法使用。使用useEffect而不是渲染后的效果。
哈桑·塞法·奥扎尔普

16

setState是异步的。您可以使用回调方法获取更新状态。

changeHandler(event) {
    this.setState({ yourName: event.target.value }, () => 
    console.log(this.state.yourName));
 }

10

使用异步/等待

async changeHandler(event) {
    await this.setState({ yourName: event.target.value });
    console.log(this.state.yourName);
}

我也一样 为我工作
人员

8

setState()操作是异步的,因此您console.log()将在setState()更改值之前执行您的操作,因此您会看到结果。

要解决此问题,请在的回调函数中记录值setState(),例如:

setTimeout(() => {
    this.setState({dealersOverallTotal: total},
    function(){
       console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
    });
}, 10)

JavaScript始终是同步的。
Santosh Singh,

1
@santoshsingh您有一个误解。API调用,超时都异步发生。
Shubham Khatri

如上所述,javascript是异步的---这是不正确的。它主要是同步的,在某些情况下是异步的。 stackoverflow.com/questions/2035645/...
桑托斯·辛格

@santoshsingh。哦,那是我的错误。句子的格式不正确
Shubham Khatri

非常巧妙地使用回调,以确保在后续调用之前更新状态!
user1204214

5

如果是钩子,则应使用useEffect钩子。

const [fruit, setFruit] = useState('');

setFruit('Apple');

useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])

很好,它可以与useEffect一起使用。但是为什么需要一个呢?
alex351

useEffect在每次重新渲染时运行,并且如果传递到数组中的项是状态变量,则它们会更改。因此,当水果更改并重新渲染组件时,该useEffect将运行。
Siraj Alam

我在useEffect之外运行setFruit和console.log水果,并且它不会更改。:/
alex351

3

setstate在反应中是异步的,因此要在控制台中查看更新的状态,请使用如下所示的回调(回调函数将在setstate更新后执行)

在此处输入图片说明

下面的方法“不推荐”,但是为了理解,如果直接改变状态,您可以在下一行看到更新的状态。我重复这是“不推荐”

在此处输入图片说明


谢谢,就是这样,您必须直接设置变量
notacorn


0

多次设置反应状态(它始终使用默认状态)时出现问题。以下这个react / github问题对我有用

const [state, setState] = useState({
  foo: "abc",
  bar: 123
});

// Do this!
setState(prevState => {
  return {
    ...prevState,
    foo: "def"
  };
});
setState(prevState => {
  return {
    ...prevState,
    bar: 456
  };
});

0

在使用一些复杂的代码的情况下,我也遇到了同样的情况,现有建议中的任何内容对我都没有用。

我的问题是setState发生在由组件之一发出的回调函数中。我的怀疑是,通话是同步进行的,setState根本无法设置状态。

简单地说,我有这样的事情:

render() {
    <Control
        ref={_ => this.control = _}
        onChange={this.handleChange}
        onUpdated={this.handleUpdate} />
}

handleChange() {
    this.control.doUpdate();
}

handleUpdate() {
    this.setState({...});
}

我不得不“修复”的方法是把doUpdate()setTimeout这样:

handleChange() {
    setTimeout(() => { this.control.doUpdate(); }, 10);
}

这并不理想,但否则将是一个重大的重构。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.