最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React hooks state variable not updating after rerender - Stack Overflow

programmeradmin11浏览0评论

In the following example I have an array of element (fruits) that I want to update and use the updated array to perform other operations (in this specific case saving the updated list). My understanding was on re rerender the state will update...but it does not here..or there is a delay between state updating and my action.

In the addFruit function I can see 'Peach' being immediately added but the console from the saveFruits function still shows the state fruit remains unchanged. How can I have this updated to use immediately. (And I know in this case I can pass newFruits variable to saveFruits to update but I need fruits to be updated for other places as well).

Forgive me because this is my millionth question about react async states but there's something just not clicking for me yet.

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="@16/umd/react.development.js" crossorigin></script>
  <script src="@16/umd/react-dom.development.js" crossorigin></script>

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

In the following example I have an array of element (fruits) that I want to update and use the updated array to perform other operations (in this specific case saving the updated list). My understanding was on re rerender the state will update...but it does not here..or there is a delay between state updating and my action.

In the addFruit function I can see 'Peach' being immediately added but the console from the saveFruits function still shows the state fruit remains unchanged. How can I have this updated to use immediately. (And I know in this case I can pass newFruits variable to saveFruits to update but I need fruits to be updated for other places as well).

Forgive me because this is my millionth question about react async states but there's something just not clicking for me yet.

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>

Share Improve this question asked Apr 8, 2019 at 21:26 bos570bos570 1,5234 gold badges25 silver badges49 bronze badges 1
  • 4 SetState is done asynchronously. Logging to console will not show the final value in state. – Eran Goldin Commented Apr 8, 2019 at 21:33
Add a comment  | 

2 Answers 2

Reset to default 12

You can try with useEffect which will give updated state whenever there will be update.

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

It's not accurate to console.log fruits because the reference to fruits is still referring to the fruits you had before you called setFruits.

If we console.log newFruits, which has the change, it would be more accurate of what is happening.

EDIT: It's probably better to useEffect as what @Atul suggested though.

It sometimes helps to visualize how this is done in old React classes. In old React classes the equivalent of this is this (to some degree not actually but close enough to illustrate the point) (Read more: 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>

We get the same problem above but it might be a little clearer. The setState for fruits does get called but the console.log happens before the state/render change happens so this.state.fruits is still referring to what was in the state before.

I highly recommend reading React hooks: not magic, just arrays to get a better sense of what goes on behind the scenes of hooks. It helps explain it a lot.

发布评论

评论列表(0)

  1. 暂无评论