Jay Jeong
Jay Jeong

Reputation: 994

componentDidMount and constructor

 class ProductsIndex extends Component {

   constructor (props){
     super(props);

     console.log(this) // #1. this logs ProductsIndex component

     fetch('someUrl')
        .then(res => res.json())
        .then(res => console.log(this)) // #2. this logs ProductsIndex component

     fetch('someUrl')
        .then(res => res.json())
        .then(console.log)  // #3. this logs [{..},{..},{..},{..}]
   }


   componentDidMount(){
     fetch('someUrl')
        .then(res => res.json())
        .then(console.log)  // #4. this logs [{..},{..},{..},{..}]

   }

As shown in the code above, both #1 and #2 point to same this. And also as shown, both #3 and #4 returns same array. However, why the code below doesn't work??

 class ProductsIndex extends Component {

   constructor (props){
     super(props);

     fetch('someUrl')
       .then(res => res.json())
       .then(arr => {
          this.state = {
              array: arr
          }
       })
    }

It throws an error saying that this.state is null and I really don't understand why.

Below code is the solution. could anyone please explain what exactly the difference is??

 class ProductsIndex extends Component {

   constructor (props){
     super(props);

     this.state = {
       array: []
     }
   }

   componentDidMount(){
      fetch('someUrl')
         .then(res => res.json())
         .then(arr => {
            this.setState({
                array: arr
             })
          })
    }

Upvotes: 19

Views: 16087

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281656

The Problem is that when you place an async request in constructor, the promise might be resolved after render phase has executed and at that point this.state is null and also since you just assign

this.state = {
    array: arr
}

and this won't lead to a re-render and so the component won't reflect the change. Having said that you should place your async requests in componentDidMount which you mention in your second attempt, and since you call setState there, a re-render is triggered and the state in reflected in render

Upvotes: 16

Related Questions