Как обрабатывать ответ API AJAX на выборку в React

Я делаю простой запрос AJAX с API-интерфейсом выборки в React, в частности, в функции componentDidMount().

Это работает, потому что консоль записывает результат. Однако я не знаю, как получить доступ к ответу...

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

Я попытался получить доступ к myData вне метода выборки, но это выдает ошибку о том, что он не определен. Таким образом, он доступен только в рамках функции.

Затем я попробовал это:

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

На этот раз я получаю Cannot read property 'setState' of undefined(…)

Как передать ответ на выборку в состояние или даже просто в глобальную переменную?


ОБНОВИТЬ

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;

person Paulos3000    schedule 30.09.2016    source источник


Ответы (6)


Насколько я вижу, у вас есть две проблемы: response.json() возвращает обещание, поэтому вы не хотите устанавливать myData в обещание, вместо этого сначала разрешите обещание, а затем вы можете получить доступ к своим данным.

Во-вторых, this не находится в той же области внутри вашего запроса на выборку, поэтому вы получаете неопределенность, вы можете попробовать сохранить область this вне выборки:

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)
person StackOverMySoul    schedule 30.09.2016
comment
большое спасибо, чувак! я потратил 3 часа на это - person Mandar Belkunde; 22.08.2018

setState не определен, потому что вы используете классический синтаксис функции вместо функции стрелки. Функция стрелки берет ключевое слово this из родительской функции, классическая функция function() {} создает собственное ключевое слово this. Попробуй это

.then(response => {
    let myData = response.json()
    // return myData;
    this.setState({
       data: myData
    })
 })
person Tomasz Nowak    schedule 30.09.2016

Вы на правильном пути с this.setState, однако this больше не находится в контексте компонента, когда вы вызываете его в функции, обрабатывающей ответ. Использование функции => поддерживает контекст this.

fetch(URL)
    .then((res) => res.json())
    .then((json) => this.setState({data: json}));
person Patrick Grimard    schedule 30.09.2016
comment
Спасибо. Это имеет смысл, но я все еще не получаю желаемого результата. Пожалуйста, взгляните на мое обновление... - person Paulos3000; 30.09.2016
comment
Вы по-прежнему ссылаетесь на this в контексте обработчика ответа, а не в контексте компонента. Вам нужно либо привязать компонент к вашей функции, либо использовать функцию с толстой стрелкой, чтобы сохранить контекст this. - person Patrick Grimard; 30.09.2016
comment
Я вижу ваше обновление сейчас. Теперь вы объявили componentDidMount с помощью функции стрелки. Это по существу ломает ваш компонент, потому что теперь this внутри этой стрелочной функции больше не находится в контексте компонента. Вы должны объявить его как componentDidMount() {}, как и раньше. Обработчик ответа из ответа на выборку — это тот, который должен использовать функцию стрелки. - person Patrick Grimard; 30.09.2016
comment
Все еще не работает: / Изменил мое обновление... myData все еще содержит значение null, которое я объявил при инициализации состояния... - person Paulos3000; 30.09.2016
comment
Вы пробовали визуализировать this.state.data в своем методе render()? Как только вы вызовете this.setState({data: myData}), он вызовет рендеринг вашего компонента. Кроме того, если вы используете Chrome, вы можете отладить это с помощью расширения React Devtools Chrome. Это позволит вам увидеть состояние вашего компонента после вызова this.setState({data: myData}). - person Patrick Grimard; 30.09.2016
comment
Да, пробовал, все равно не работает, к сожалению. Я посмотрю, что я могу сделать с Chrome React Devtools... - person Paulos3000; 30.09.2016
comment
На этом этапе стоило бы увидеть ваш полный компонент. Может быть, там есть что-то, чего я не вижу. - person Patrick Grimard; 30.09.2016
comment
Никогда не используя fetch API, я думаю, что нашел проблему. вызов response.json() на самом деле не возвращает JSON, он возвращает Promise. Таким образом, место для вашего this.setState находится в возврате от этого обещания. Я обновил свой ответ. - person Patrick Grimard; 01.10.2016

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 создайте файл answermsg.json и поместите ниже содержимое, и он должен размещаться на локальном хосте, например: http://localhost/replymsg.json

{"status":"200ok","CurrentID":28,"msg":"msg successfully reply"}
person Brijmohan Karadia    schedule 07.03.2017

Измените способ доступа к данным ответа, используя '=>' вместо функции, чтобы быть в том же контексте.

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
person Ye Yint    schedule 14.09.2017

Вам нужно привязать текущий контекст к целевой функции

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)
         })
person Floyd    schedule 09.12.2016