【问题标题】:React setState not updating state反应 setState 不更新状态
【发布时间】:2021-01-28 09:31:09
【问题描述】:

所以我有这个:

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。
  • @FelixKling 不,我在调用 this.state 在我设置它之后。我之前正在记录一个变量。没有?
  • 由于超时,您的setState 确实在您记录状态后执行。我认为您在调试中要做的是将console.log 部分放在超时内,将setState 放在外面。
  • @FabianSchultz 你能解释一下我当时没明白的一件事吗?考虑这段代码:if(this.state.playersOverallTotal > 21){ console.log('bust'); this.setState({playerBusted: true}); } 当它超过 21 时,日志会触发,但状态不会改变,只有在数字再次增加时才会改变。例如如果它达到 24,它不会设置状态,但如果它达到 28,例如它会

标签: javascript reactjs state setstate


【解决方案1】:

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

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

【讨论】:

  • 除此之外,OP 显式记录状态值之前他们调用setState。
  • 这也适用于我,过去我使用过这个:`this.setState({someVar: newValue},function(){ console.log("force update}); '但是出于某种原因,当我按照上面的描述更新代码时,它不再担心了。知道为什么吗?
  • @Jozcar 应该也可以,语法不正确(缺少括号):this.setState({someVar: newValue},function(){ console.log("force update") });
  • imgur.com/Ku0OjTl 请告诉我该怎么做才能摆脱这个问题。
  • 我完全忘记了它是异步调用的事实,并且做了所有可能的代码更改,除了这个,在这里你让我的大脑免于烧毁。谢谢
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    如果是钩子,你应该使用useEffect钩子。

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

    【讨论】:

    • 很好,它可以与 useEffect 一起使用。但为什么它需要一个?
    • useEffect 在每次重新渲染时运行,如果传入数组的项目是状态变量,则沙子已更改。因此,当水果发生变化并且组件重新渲染时,useEffect 将运行。
    • 我在 useEffect 之外运行 setFruit 和 console.log 水果,它没有改变。 ://
    【解决方案4】:

    使用异步/等待

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

    【讨论】:

    • setState 不返回承诺,所以我不希望这会起作用。
    【解决方案5】:

    setState在react中是异步的,所以要在控制台看到更新的状态,使用回调如下图(回调函数会在setState更新后执行)

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

    【讨论】:

    • THANK YOU 就这样,你要直接设置变量
    【解决方案6】:

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

    为了解决这个问题,在setState()的回调函数中记录值,比如:

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

    【讨论】:

    • JavaScript 总是同步的。
    • @santoshsingh 你有一个误解。 API 调用、超时都是异步发生的。
    • 正如您在上面提到的,javascript 是异步的——这是不正确的。它主要是同步的,在某些情况下它是异步的。 stackoverflow.com/questions/2035645/…
    • @santoshsingh。哦,那是我的一个错误。没有正确形成句子
    • 非常巧妙的利用回调来保证状态在后续调用之前更新!
    【解决方案7】:

    我在多次设置反应状态时遇到了问题(它总是使用默认状态)。关注这个react/github 问题对我有用

    const [state, setState] = useState({
      foo: "abc",
      bar: 123
    });
    
    // Do this!
    setState(prevState => {
      return {
        ...prevState,
        foo: "def"
      };
    });
    setState(prevState => {
      return {
        ...prevState,
        bar: 456
      };
    });
    

    【讨论】:

    • 设置这样的状态为我修复了它
    【解决方案8】:

    我在一些复杂的代码中遇到了同样的情况,现有的建议对我没有任何帮助。

    我的问题是 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);
    }
    

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

    【讨论】:

    • 这解决了我的问题,但我将 setState() 放在 setTimeout() 中。谢谢!
    • 非常感谢。你刚刚让我免于更多的调试。
    【解决方案9】:

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

    【讨论】:

    • 感谢您离开这里。您的评论为我指明了正确的方向。我发现有问题的代码在冲突事件中被更新,然后在那个地方我使用 prevState 回调设置新状态,如上所述 @Arun Gopalpuri ``` this.setState(prevState=>{ return {...prevState, newProperty }}); ```
    【解决方案10】:

    只需在您的代码中添加componentDidUpdate(){} 方法,它就会起作用。 你可以在这里查看 react native 的生命周期:

    https://images.app.goo.gl/BVRAi4ea2P4LchqJ8

    【讨论】:

      【解决方案11】:

      如果您使用函数,则需要使用 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>
       );
      }
      

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

      【讨论】:

        猜你喜欢
        • 2021-06-02
        • 2018-12-08
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        相关资源
        最近更新 更多