【问题标题】:React hooks state variable not updating after rerenderReact 钩子状态变量在重新渲染后不更新
【发布时间】:2019-08-30 02:37:54
【问题描述】:

在下面的示例中,我有一个要更新的元素(水果)数组,并使用更新后的数组来执行其他操作(在这种特定情况下,保存更新后的列表)。我的理解是重新渲染状态将更新......但它没有在这里......或者状态更新和我的操作之间存在延迟。

addFruit 函数中,我可以看到立即添加了“Peach”,但来自saveFruits 函数的控制台仍显示状态fruit 保持不变。我怎样才能让这个更新立即使用。 (我知道在这种情况下我可以将newFruits 变量传递给saveFruits 进行更新,但我也需要fruits 来更新其他地方)。

请原谅我,因为这是我关于反应异步状态的第 100 万个问题,但有些东西还没有让我点击。

const { useState } = React;

function ParentComp() {
    const[fruits, setFruits] = useState(['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi'])


   const addFruit = () => {
      let newFruits = Object.assign([], fruits)
      newFruits.push('Peach')
      setFruits(newFruits)
      saveFruits()
   }
   
   const saveFruits = () => {
      console.log('API req to save fruits.', fruits)
   }

   return (
    <div>
    { fruits.map( (fruit, key) => <div key={key}>{fruit}</div> ) }
      <button type="button" onClick={addFruit}>Add Peach</button>
    </div>
   )
}

ReactDOM.render(<ParentComp />, document.getElementById('root'))
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

<div id="root"></div>

【问题讨论】:

  • SetState 是异步完成的。登录到控制台不会在状态中显示最终值。

标签: javascript reactjs react-hooks


【解决方案1】:

您可以尝试使用 useEffect,它会在有更新时提供更新状态。

useEffect(() => {
    saveFruits();
  }, [fruits]);

【讨论】:

  • 如果我们在 useEffect 中调用任何 REST API 会怎样?
【解决方案2】:

console.log fruits 不准确,因为对 fruits 的引用仍然是指您在调用 setFruits 之前拥有的 fruits

如果我们console.log newFruits,它有变化,它会更准确地了解正在发生的事情。

编辑:useEffect 可能会更好,就像 @Atul 建议的那样。

它有时有助于可视化在旧的 React 类中是如何完成的。在旧的 React 类中,与此等价的是(在某种程度上实际上不是,但足够接近以说明这一点)(阅读更多:https://reactjs.org/docs/hooks-state.html

class ParentComp extends React.Component {
  constructor() {
    super();
    this.state = {
      fruits: ['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi']
    };
  }

  addFruit = () => {
    let newFruits = Object.assign([], this.state.fruits);
    newFruits.push('Peach')
    this.setFruits(newFruits)
    this.saveFruits();
  }

  setFruits = (fruits) => {
    this.setState({
      fruits
    });
  }

  saveFruits = () => {
    console.log(this.state.fruits);
  }

  render() {
    return ( 
        <div> 
         {this.state.fruits.map((fruit, key) => {
          return (<div key={key}>{fruit}</div>) })} 
          <button type="button" onClick={this.addFruit}>Add Peach</button>
        </div>
    );
  }
}
ReactDOM.render(<ParentComp /> , document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

我们在上面遇到了同样的问题,但可能更清楚一点。 fruits 的 setState 确实被调用了,但 console.log 发生在状态/渲染更改发生之前,所以 this.state.fruits 仍然指的是之前的状态。

我强烈建议阅读React hooks: not magic, just arrays 以更好地了解挂钩幕后发生的事情。它有助于解释它。

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 2020-06-26
    • 2020-04-07
    • 2016-11-04
    • 1970-01-01
    • 2021-05-19
    • 2022-01-26
    • 1970-01-01
    • 2020-01-01
    相关资源
    最近更新 更多