React setState不更新状态

The*_*orm 54 javascript state setstate reactjs

所以我有这个:

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
Run Code Online (Sandbox Code Playgroud)

newDealersDeckTotal只是一个数字数组,[1, 5, 9]但是this.state.dealersOverallTotal不能给出正确的总数但是total呢?我甚至提出了超时延迟,看看是否解决了这个问题.任何明显的或我应该发布更多的代码?

Fab*_*ltz 111

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

this.setState({ dealersOverallTotal: total }, () => {
  console.log(this.state.dealersOverallTotal, 'dealersOverallTotal1');
}); 
Run Code Online (Sandbox Code Playgroud)

  • 除此之外,OP 明确记录了*before* 调用`setState` 的状态值。 (2认同)

Aru*_*uri 19

我在多次设置反应状态时遇到问题(它始终使用默认状态)。遵循这个react/github问题对我有用

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

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

  • 像这样设置状态为我解决了这个问题 (2认同)

Mok*_*h S 17

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

this.setState({ email: 'test@example.com' }, () => {
   console.log(this.state.email)
)}
Run Code Online (Sandbox Code Playgroud)


Dev*_*v01 14

使用异步/等待

async changeHandler(event) {
    await this.setState({ yourName: event.target.value });
    console.log(this.state.yourName);
}
Run Code Online (Sandbox Code Playgroud)

  • `setState` 不返回承诺,所以我不希望它起作用。 (2认同)

Sir*_*lam 14

在钩子的情况下,你应该使用useEffect钩子。

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

setFruit('Apple');

useEffect(() => {
  console.log('Fruit', fruit);
}, [fruit])
Run Code Online (Sandbox Code Playgroud)


Mah*_*shi 9

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

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


Shu*_*tri 7

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

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

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

  • @santoshsingh你有一个误解。API 调用、超时都是异步发生的。 (3认同)

Gus*_*utt 6

除了注意 setState 的异步性质外,还要注意您可能有竞争的事件处理程序,一个执行您想要的状态更改,另一个立即再次撤消它。例如,父组件也处理 onClick 的组件上的 onClick。通过添加跟踪来检查。通过使用 e.stopPropagation 来防止这种情况。


Dan*_*alà 6

如果您使用函数,则需要使用 UseEffect 来处理 setState 的异步性(不能像使用类时那样使用回调)。一个例子:

import { useState, useEffect } from "react";

export default function App() {
 const [animal, setAnimal] = useState(null);

 function changeAnimal(newAnimal) {
  setAnimal(newAnimal);
  // here 'animal' is not what you would expect
  console.log("1", animal);
 }

 useEffect(() => {
  if (animal) {
   console.log("2", animal);
  }
 }, [animal]);

 return (
  <div className="App">
  <button onClick={() => changeAnimal("dog")} />
 </div>
 );
}
Run Code Online (Sandbox Code Playgroud)

第一个 console.log 返回 null,第二个返回“dog”


zme*_*nic 5

我遇到了同样的情况,有一些复杂的代码,现有的建议对我来说没有任何作用。

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

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

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

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

handleUpdate() {
    this.setState({...});
}
Run Code Online (Sandbox Code Playgroud)

我必须“修复”它的方法是这样doUpdate()输入:setTimeout

handleChange() {
    setTimeout(() => { this.control.doUpdate(); }, 10);
}
Run Code Online (Sandbox Code Playgroud)

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