Вызов Rest API из приложения REACT всегда возвращает isLoaded: false

#node.js #reactjs

#node.js #reactjs

Вопрос:

 import React from 'react';
import './App.css';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      items: [],
      isLoaded: false
    };
  }

  callAPI() {
    fetch("http://localhost:4000/api/process/4570")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items
          });
        },
        // Note: it's important to handle errors here
        // instead of a catch() block so that we don't swallow
        // exceptions from actual bugs in components.
        (error) => {
          this.setState({
            isLoaded: false,
            error
          });
        }
      )
  }

  componetDidMount() {
    this.callAPI();
  }


  render() {
    var { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    }
    else {

      return (
        <div className="App">
          <ul>
            {items.map(item => (
              <li key={item.id} >
                Id: {item.id} | Name: {item.name}
              </li>
            ))}
          </ul>
        </div>
      );
    }
  }
}
export default App;  

консоль: ошибки нет.
react-developer-tool: возвращает
состояние =
{
«ошибка»: null,
«элементы»: [],
«isLoaded»: false
}

Я очень новичок в REACT и API. Пожалуйста, объясните мне, какую ошибку я допустил здесь. Я не могу получить вывод API. Я всегда получаю «загрузку»

API возвращает json: {«id»:»4570″,»name»:»AR_RESUME_CNC_ROUTING»}

Ответ №1:

вам нужно установить isLoading значение true в вашей callApi функции перед всем остальным, после этого вам нужно установить значение false при получении результата или при обнаружении какой-либо ошибки.

 callAPI() {

    this.setState({
      isLoading: true,
    });

    fetch("http://localhost:4000/api/process/4570")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoading: false,
            items: result.items
          });
        },
        (error) => {
          this.setState({
            isLoading: false,
            error
          });
        }
      )
  }


  

небольшое объяснение кода, вы всегда хотите показывать загрузку при начале вашего вызова api, поэтому мы устанавливаем isLoading в начале функции, затем, когда мы получаем результат (успех или неудача, не имеет значения), состояние загрузки должно измениться на false, потому что у нас есть хотя бы результат!

также в качестве дополнительного момента вы можете использовать try {...} catch {...} finally {...} лучший стиль кода, как показано ниже:

 async callApi() {

  try {
    
    this.setState({ isLoading: true })

    const result = await fetch("http://localhost:4000/api/process/4570")
    const data = await result.json()
    
    this.setState({
       items: result.items
    });
   
  } catch (e) {
    this.setState({ error: e })
  } finally {
    this.setState({ isLoading: false })
  }

}

  

Комментарии:

1. Обратите внимание, что это isLoaded , а не isLoading 🙂

2. также вам необходимо изменить значение else if (!isLoaded) { на else if (isLoaded) {

3. Я имел в виду, что переменная, используемая в вопросе, не представляет «загружается в данный момент», а «завершила загрузку» — полная противоположность вашему примеру.

Ответ №2:

Мне кажется, это какая-то проблема с областью действия. Вы делаете:

 this.setState({
    isLoaded: true,
    items: result.items
});
  

но вы вызываете его в рамках обратного вызова функции обещания выборки. Итак, this вероятно, ссылается на внутренний объект Promise.

Я рекомендую вам попробовать это:

 callAPI() {
    const self = this;
    fetch("http://localhost:4000/api/process/4570")
      .then(res => res.json())
      .then(
        (result) => {
          self.setState({
            isLoaded: true,
            items: result.items
          });
        },
        // Note: it's important to handle errors here
        // instead of a catch() block so that we don't swallow
        // exceptions from actual bugs in components.
        (error) => {
          self.setState({
            isLoaded: false,
            error
          });
        }
      )
   }
  

Повторно ссылайтесь на this, на новую переменную (в данном случае я использовал self) и попробуйте свой код там.

Ответ №3:

Спасибо за ваш ответ, однако решение, которое сработало для меня, выглядит следующим образом:

 class GetOnlinePosts extends Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            loading: true,
            posts: null,
        };
    }

    async componentDidMount() {
        console.log("inside external_json");
        const url = "http://localhost:4000/api/process/4570";
        const response = await fetch(url);
        const data = await response.json();
        this.setState({ posts: data, loading: false })
        console.log(data);
    }
  

………..