1

I extract data from my "ComponentDidMount" function and load them in my state. Straight after I console log the value and see everything is there. However, when I try to access the state the same way in my return in my render function, I will get "undefined".

public componentDidMount() {
sp.web.lists.getByTitle("alert").items.get().then((item) => {
  this.setState({items: item})
  console.log(this.state.items[0].Title) //works
})

}

Above console log "(this.state.items[0].Title)" works. I try to use the state the same way in my render function:

 <span className={ styles.title }>{this.state.items[0].Title}</span>

Does not work, and the value is undefined. How come? I store the data in my state when the component is loaded, and expected the data to be there when I refered to state in my render. How come?

Arte2
  • 309
  • 4
  • 19
  • In the component did mount it works because it only tries to do it after the component is rendered..when the component renders it is first undefined. You will have to check it has a value first before displaying it...in your render – Talmacel Marian Silviu Jun 22 '20 at 16:04
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – HMR Jun 22 '20 at 16:06
  • If you don't know why render is called before setState then maybe read about [promises](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch3.md) – HMR Jun 22 '20 at 16:08

1 Answers1

3

componentDidMount is called after the initial render of the component. So when render function is called for the first time, this.state.items[0].Title would be undefined.

Once the component has rendered, then componentDidMount will execute and update the state and re-render your component.

Inside the render function, access Title property only if this.state.items[0] is defined.

<span className={ styles.title }>
   { this.state.items[0] && this.state.items[0].Title }
</span>

One more thing that you should be aware of is that this.setState function updates the state asynchronously, so trying to log the state immediately after this.setState function call will give you the previous value of state.

If you want to log the latest state, you could pass an optional second argument to this.setState function. This second argument is a callback function which is called after state has been updated.

this.setState({items: item}, () => {
    console.log(this.state.items[0].Title)
})
Yousaf
  • 27,861
  • 6
  • 44
  • 69