Ando
Ando

Reputation: 1847

setState from an API response using superagent and React

I get an error when trying to change the state of a component.

Uncaught TypeError: Cannot read property 'setState' of undefined

constructor(props){
    super(props);

    this.state={
        r:'',
        message:''
    };
    this.setStateMessage = this.setStateMessage.bind(this);
}
setStateMessage (e){
    e.preventDefault();
    var test = this.state.message;

    request
      .post('http://127.0.0.1:5000/api/db')
      .send({message: this.state.message})
      .accept('application/json')
      .withCredentials()
      .end(function(err, res){
        if(err)
            throw err;
        this.setState({ r: res.body.message });
      });
}

render() {
    return (
        <div>
            <div className='response'>
                {this.state.r}
            </div>
            //form with input
        </div>
    )}

Upvotes: 2

Views: 3461

Answers (3)

Ain
Ain

Reputation: 748

After spending too much time on this my final code is here

class Data extends React.Component{

     constructor(){
        super()
        this.state={
            name:''
        }
    }

    componentDidMount(){
        console.log('componentDidMount');

        var url = "http:\//localhost:3000/order/test";
        Request
        .get(url)
        .query(null)
        .set('Accept', 'application/json')
        .end ((error, response)=>{
            const title=response.text
            console.log(JSON.stringify(title));

            this.setState({
              name:title
            });
        });

    }

    render(){
        return <div>World {this.state.name}</div>;
    }

}

Note: If response is a text you have to use response.text as I use in my case

If you want more detail click here

Upvotes: 0

xyc
xyc

Reputation: 181

To add to @aray12's answer, you can bind the callback too.

setStateMessage (e){
  e.preventDefault();
  var test = this.state.message;

  request
    .post('http://127.0.0.1:5000/api/db')
    .send({message: this.state.message})
    .accept('application/json')
    .withCredentials()
    .end((function(err, res) {
      if(err) throw err;
      this.setState({ r: res.body.message });
  }).bind(this));
}

Upvotes: 2

aray12
aray12

Reputation: 1843

This is because you are calling this.setState from within a function so this is actually a reference to the function you are in. You need to either store a reference to the correct this or use an arrow which does not have its own context and inherits from the parent context. So:

setStateMessage (e){
  e.preventDefault();
  var test = this.state.message;
  var self = this;

  request
    .post('http://127.0.0.1:5000/api/db')
    .send({message: this.state.message})
    .accept('application/json')
    .withCredentials()
    .end(function(err, res){
      if(err) throw err;
      self.setState({ r: res.body.message });
  });
}

Or:

setStateMessage (e){
  e.preventDefault();
  var test = this.state.message;

  request
    .post('http://127.0.0.1:5000/api/db')
    .send({message: this.state.message})
    .accept('application/json')
    .withCredentials()
    .end((err, res) => {
      if(err) throw err;
      this.setState({ r: res.body.message });
  });
}

Upvotes: 6

Related Questions