Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle fetch API AJAX response in React

I am making a simple AJAX request with the fetch API in React, specifically in the componentDidMount() function.

It is working, because the console appears to be logging the result. However, I don't know how to access the response...

componentDidMount = () => {

      let URL = 'https://jsonplaceholder.typicode.com/users'

         fetch(URL)
         .then(function(response) {
            let myData = response.json()
            return myData;
         })
         .then(function(json) {
            console.log('parsed json', json)
         })
         .catch(function(ex) {
            console.log('parsing failed', ex)
         })

   } // end componentDidMount

I tried accessing myData outside of the fetch method, but this throws an error saying that it is undefined. So it is only accessible within the scope of the function.

I then tried this:

     .then(function(response) {
        let myData = response.json()
        // return myData;
        this.setState({
           data: myData
        })
     })

This time, I get Cannot read property 'setState' of undefined(…)

How do I pass the fetch response to the state, or even just a global variable?


UPDATE

import React, { Component } from 'react';
import './App.css';

class App extends Component {

   constructor(props) {
      super(props);
      this.state = {
         data: null
      }
   }

   componentDidMount() {
      let URL = 'https://jsonplaceholder.typicode.com/users'  
         fetch(URL)
         .then( (response) => {
            let myData = response.json()
            // return myData;
            this.setState({
               data: myData
            })
         })
         .then( (json) => {
            console.log('parsed json', json)
         })
         .catch( (ex) => {
            console.log('parsing failed', ex)
         })
         console.log(this.state.data)
   } // end componentDidMount

  render() {
    return (
      <div className="App">
         {this.state.data}
      </div>
    );
  }
}

export default App;
like image 975
Paulos3000 Avatar asked Sep 30 '16 19:09

Paulos3000


4 Answers

You have two issues as far as I can see, response.json() returns a promise, so you don't wanna set myData to the promise, instead first resolve the promise and then you can access your data.

Second, this is not in the same scope inside your fetch request, so that's why you are getting undefined, you can try saving the scope of this outside fetch:

var component = this;

fetch(URL)
 .then( (response) => {
    return response.json()    
 })
 .then( (json) => {
    component.setState({
       data: json
    })
    console.log('parsed json', json)
 })
 .catch( (ex) => {
    console.log('parsing failed', ex)
 })
 console.log(this.state.data)
like image 79
StackOverMySoul Avatar answered Nov 09 '22 15:11

StackOverMySoul


setState is undefined, because you use classic function syntax instead arrow function. Arrow function takes 'this' keyword from 'parent' function, a classic function() {} creates it's own 'this' keyword. Try this

.then(response => {
    let myData = response.json()
    // return myData;
    this.setState({
       data: myData
    })
 })
like image 44
Tomasz Nowak Avatar answered Nov 09 '22 14:11

Tomasz Nowak


You're on the right track with this.setState however this is no longer in the context of the component when you call it within the function handling the response. Using a => function maintains the context of this.

fetch(URL)
    .then((res) => res.json())
    .then((json) => this.setState({data: json}));
like image 3
Patrick Grimard Avatar answered Nov 09 '22 16:11

Patrick Grimard


REACT NATIVE

import React, { Component } from 'react';

import {
AppRegistry,
StyleSheet,
Text,
View,
} from 'react-native';

export default class SampleApp extends Component {
constructor(props) {
super(props);
this.state = {
    data:  'Request '
    }
}

componentDidMount = () => {
fetch('http://localhost/replymsg.json', {
                      mode: "no-cors",
                      method: "GET",
                      headers: {
                        "Accept": "application/json"
                      },} )
                      .then(response => {
                      if (response.ok) {

                          response.json().then(json => {

                            console.warn( JSON.stringify(json.msg ));
                              this.setState({
                                 data: JSON.stringify(json)
                            })

                        });
                      }
                    }); 

}



render() { 
return (
    <Text>  {this.state.data}</Text>
    );
    }
}

AppRegistry.registerComponent('SampleApp', () => SampleApp);

JSON FILE create a file replymsg.json and put below content and it should host to local host like : http://localhost/replymsg.json

{"status":"200ok","CurrentID":28,"msg":"msg successfully reply"}
like image 1
Brijmohan Karadia Avatar answered Nov 09 '22 16:11

Brijmohan Karadia