简体   繁体   中英

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;

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)

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
    })
 })

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}));

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"}

Change the way you access the response data by using '=>' instead of function to be in the same context.

componentDidMount = () => {

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

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

} // end componentDidMount

You need to bind current context to the target function

fetch(URL)
         .then(function(response) {
            return response.json();
         })
         .then(function(json) {
            this.setState({data: json})
         }.bind(this))
         .catch(function(ex) {
            console.log('parsing failed', ex)
         })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM