user308553
user308553

Reputation: 1250

componentDidUpdate inner working confuses me

One of my React component receive a Array of JSON. And the component contain a componentDidUpdate. I know this function run right before rendering, and I get to see the nextProps and nextState, so I can compare them with the current. However the inner working confuses me


Here are the steps of my program:

  1. parent Component pass newly updated list to this component
  2. This component run componentDidUpdate:

    • Compare old list to this new updated list. Find the newly added item, push it into this component's state (an array call differenceList)
  3. this component render according to the differenceList


Following is my console.log that I've placed all over.

//after I trigger a update of the list

  1. Entering ComponentWillUpdate
  2. Found the unique item: "1336" and next line of code push it into array
  3. Should have just pushed it into array with self.setState({differenceList: self.state.differenceList.concat(item.id)});
  4. reached end of ComponentWillUpdate, this.state.differenceList is: [] //what??
  5. Entering rendering function, this.state.differenceList is: []
  6. Entering ComponentWillUpdate //why again?
  7. end of ComponentWillUpdate, this.state.differenceList is: []
  8. Entering rendering function, this.state.differenceList is: ["1336"]

why is #4 showing empty??

at #6 why did it enter componentWillUpdate again? is it because I updated the state inside componentWillUpdate? but if so why is #5 showing empty state #8 Now after entering render function again, it suddenly show the changed state

Upvotes: 1

Views: 242

Answers (1)

yachaka
yachaka

Reputation: 5569

The answer is because setState is asynchronous.

  1. <Parent/> tries to render <Child list={[1, 2, 1336]}/> (Batch 0)
    • willUpdate() gets called with nextProps = {list: [1, 2, 1336]}
    • self.setState({differenceList: self.state.differenceList.concat(['1336'])}) // This code is asynchronous, creating Batch 1
    • End of willUpdate(), this.state is still the same
    • render()
  2. Treating Batch 1 (your setState() call)
    • willUpdate() with nextState = { ... differenceList: ['1336'] }
    • this.state still not updated
    • End of willUpdate()
    • render() with new state

I'm not sure I'm being very clear, I'm a bit tired.
Anyways, you should not be using this.setState in componentWillUpdate().
Try using componentWillReceiveProps() for your purposes.

Upvotes: 2

Related Questions