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
})
})
}
The componentDidMount() method allows us to execute the React code when the component is already placed in the DOM (Document Object Model). This method is called during the Mounting phase of the React Life-cycle i.e after the component is rendered.
componentDidMount. The componentDidMount() method is called after the component is rendered. This is where you run statements that requires that the component is already placed in the DOM.
If you will see carefully in the console panel, then it first logs “First this called” and then our initial state is defined and then render() method is called then componentDidMount() method is called and then newly fetched data is displayed in the component.
All the network requests that are to be made when the props passed to the component changes are coded here. The componentDidUpdate()is called after componentDidMount() and can be useful to perform some action when the state of the component changes.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With