React question - Cannot read property 'setState' of undefined

I am getting this error and am not able to load my data as a result even though it is there.

import React, { Component } from 'react'
import Comment from '../presentation/Comment';
import CreateComment from '../presentation/CreateComment';
import styles from '../layout/styles';
import Api from '../../utils/ApiManager';

class Comments extends Component {
	constructor() {
		super()
		this.state = {
			list: []
		}
	}
    // override this function
	componentDidMount(){
		console.log('Comments componentDidMount: ');
		Api.get('/api/comment', null, function(err, response) {
			if (err) { alert("Error: " + err); return;}
			
			console.log('RESULTS: ' + JSON.stringify(response.message));

            
            this.setState({
                list: response.message
            })
		})
	
	}
	

    submitComment(comment){
        console.log("Submitting comment" + JSON.stringify(comment));
        
        let updatedComment =Object.assign({}, comment);
        Api.post('/api/comment', updatedComment, (err, response) => {
            if(err) {alert(err); return;}
            
            let updatedList = Object.assign([], this.state.list);
            updatedList.push(response.message);

            this.setState({
                list: updatedList
            })
        })
        
    }
    
    
    render() {
        const commentStyle = styles.comment;
        const commentList = this.state.list.map((comment, i) => {
            return (
                <li key={i}><Comment currentComment={comment} /></li>
            )
        });
        return (
            <div>
                <h2>Comments for ...Zone [1]</h2>
                <div style={commentStyle.commentsBox}>
                    <ul style={commentStyle.commentList}>{commentList}</ul>
                </div>
                <CreateComment onCreate={this.submitComment.bind(this)} />
            </div>
        )
    }
    
}

export default Comments

I’m not sure if it’s related, but you need to pass props to both your constructor and super

constructor(props) {
		super(props)
		this.state = {
			list: []
		}
	}

Ok, I tried that but the error still persists.

Oh, it’s so obvious now. You’re calling this.setState inside of your callback to Api.get(). You need to cache the reference to this outside of that API call.

componentDidMount(){
  let currentComponent = this;

  Api.get('/api/comment', null, function(err, response) {
    if (err) { alert("Error: " + err); return;}

    currentComponent.setState({
      list: response.message
    })

  })
}
4 Likes

Why do arrow functions make a difference?

That’s fixed it. Well done. Still new to React so this doesn’t make much sense at the moment.

This is the correct answer, the arrow function binds this for you so you can access it within the function and it will still point to the component.

For some reason my project wasn’t working with arrow functions. Hence why I used a normal function declaration instead.

That’s strange. What happens when you try?

Getting same issue in console, can’t figure out what’s wrong.
can anyone help?

my code:-

class App extends Component {

constructor(){
    super()

    //state for characters value//
    this.state = {
        characters : []
    }
 
}

componentDidMount(){
    this.fetchData()
}
//function to call SWAPI and get data.
fetchData = () => {
    axios.get('https://swapi.co/api/people').then(function(response) {
        const data = response.data.results
        console.log(data)

        this.setState({
            characters : data
        })
    })
}

render() {

    return(
        <div>
            <Header/> 
            <CharacterList characters={this.state.characters}/>
        </div>
    )
}

}

export default App

What is the error? Did the console print the correct data? Have you import axios?

You should use arrow function:

axios.get('https://swapi.co/api/people').then((response) => {

Also don’t post in 2 years old topics. Create your own.

yes, i imported axios, and console.log prints the exact data that I want.

Error:-
Uncaught (in promise) TypeError: Cannot read property ‘setState’ of undefined
at eval (App.js:29)

Can’t believe that worked and I was that stupid. I always use arrow functions because it eliminated the need to bind it but forgot it there.

Thanks a lot, everyone, and @jenovs sorry, I will keep that in mind.

Thanks a ton, was not able to find the RCA for this issue got it now :slight_smile:

1 Like

thanks that help me a lot