bier hier
bier hier

Reputation: 22570

How to use response data from ajax call in react?

I have just started with learning reactjs and trying to retrieve data through an ajax call. The component looks like this:

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';

class App extends React.Component {
   // myTitle='';

    constructor() {
        super();
        this.state = {val: 0};
        this.update = this.update.bind(this);
    }

    update() {
        var root = 'http://jsonplaceholder.typicode.com';
        $.ajax({
            url: root + '/posts/1',
            method: 'GET'
        }).then(function (data) {
            this.state.val = data.title;
        });

        console.log(this.state);
    }

    componentWillMount() {
        console.log('mounting')
    }

    render() {
        console.log('rendering!')
        return <button onClick={this.update}>{this.state.val}</button>
    }

    componentDidMount() {
        console.log('mounted')
    }

    componentWillUnmount() {
        console.log('bye!')
    }
}

When the ajaxcall comes back it returns an error where the state.val statement is:

jQuery.Deferred exception: Cannot set property 'val' of undefined TypeError: Cannot set property 'val' of undefined
    at Object.<anonymous> (http://localhost:3000/08-lifecycle-mounting/index.js:28958:33)
    at mightThrow (http://localhost:3000/08-lifecycle-mounting/index.js:32563:30)
    at process (http://localhost:3000/08-lifecycle-mounting/index.js:32631:13) 

How can I update the state and use the returning data from the ajax call?

Upvotes: 1

Views: 2373

Answers (1)

Piotr Berebecki
Piotr Berebecki

Reputation: 7468

Here is a demo of how you could display the data fetched with your AJAX request: http://codepen.io/PiotrBerebecki/pen/ALQxbE

First of all, in order to update your state inside the update method, follow React's official docs (https://facebook.github.io/react/docs/component-api.html#setstate):

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

So this line in your code:

this.state.val = data.title;

should become:

this.setState({val: data.title})

Then, the next thing to solve is to make sure that this.setState refers to your class when called inside the $.ajax()call. You can achieve this in two ways:

1. Using an arrow function:

$.ajax({
  url: root,
  method: 'GET'
}).then(data => {
  let randomNumber = Math.floor(Math.random() * data.length);
  this.setState({title: data[randomNumber].title});
});

2. Using bind(this):

$.ajax({
  url: root,
  method: 'GET'
}).then(function(data) {
  let randomNumber = Math.floor(Math.random() * data.length);
  this.setState({title: data[randomNumber].title});
}.bind(this));

Also, note that, inside your update method when you try to use console.log(this.state) straight after updating state, you will not see the updated state for reasons explained here: https://stackoverflow.com/a/39804336/4186037

Upvotes: 1

Related Questions