Используйте Async / Await с Axios в React.Яш

Я пытаюсь сделать простой запрос get на мой сервер, используя Async / Await в React.приложение на JS. Сервер загружает простой JSON в /data выглядит так:

JSON

{
   id: 1,
   name: "Aditya"
}

Я могу получить данные в приложение React с помощью простого метода jQuery ajax get. Однако я хочу использовать библиотеку axios и Async/Await, чтобы следовать стандартам ES7. Мой текущий код выглядит так:

class App extends React.Component{
 async getData(){
     const res = await axios('/data');
     console.log(res.json());
 }
 render(){
     return(
         <div>
             {this.getData()}
         </div>
     );
 }
}

используя этот подход, я получаю следующее ошибка:

объекты недопустимы в качестве дочернего элемента React (найдено: [обещание объекта]). Если вы хотели отобразить коллекцию детей, вместо этого используйте массив.

Я не правильно его реализовать?

2 ответов


выскакивают два вопроса:

  1. код getData никогда ничего не возвращает, поэтому его обещание (async функции всегда возвращают обещание) разрешат с undefined при разрешении

  2. сообщение об ошибке ясно показывает, что вы пытаетесь напрямую отобразить обещание getData возвращает, а не ждет его разрешения, а затем рендеринга разрешения

Решение #1: getData должны возвращение результат вызова json:

async getData(){
   const res = await axios('/data');
   return await res.json();
}

Addressig #2: Нам нужно было бы увидеть больше вашего кода, но, по сути, вы не можете этого сделать

<SomeElement>{getData()}</SomeElement>

...потому что это не ждет разрешения. Вместо этого вам нужно использовать getData установить состояние:

this.getData().then(data => this.setState({data}))
              .catch(err => { /*...handle the error...*/});

...и используйте это состояние при рендеринге:

<SomeElement>{this.state.data}</SomeElement>

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

class App extends React.Component{
    async getData() {
        const res = await axios('/data');
        return await res.json(); // (Or whatever)
    }
    constructor(...args) {
        super(...args);
        this.state = {data: null};
    }
    componentDidMount() {
        if (!this.state.data) {
            this.getData().then(data => this.setState({data}))
                          .catch(err => { /*...handle the error...*/});
        }
    }
    render() {
        return (
            <div>
                {this.state.data ? <em>Loading...</em> : this.state.data}
            </div>
        );
    }
}

дополнительные обновления: вы указали предпочтение использования await на componentDidMount, а не then и catch. Вы бы сделали это, вложив async функция IIFE внутри него и обеспечение того, что функция не может бросить. ( не может быть async, ничто не поглотит это обещание.) Например:

class App extends React.Component{
    async getData() {
        const res = await axios('/data');
        return await res.json(); // (Or whatever)
    }
    constructor(...args) {
        super(...args);
        this.state = {data: null};
    }
    componentDidMount() {
        if (!this.state.data) {
            (async () => {
                try {
                    this.setState({data: await this.getData()});
                } catch (e) {
                    //...handle the error...
                }
            })();
        }
    }
    render() {
        return (
            <div>
                {this.state.data ? <em>Loading...</em> : this.state.data}
            </div>
        );
    }
}

по моему опыту за последние несколько месяцев я понял, что лучший способ достичь этого:

class App extends React.Component{
  constructor(){
   super();
   this.state = {
    serverResponse: ''
   }
  }
  componentDidMount(){
     this.getData();
  }
  async getData(){
   const res = await axios.get('url-to-get-the-data');
   const { data } = await res;
   this.setState({serverResponse: data})
 }
 render(){
  return(
     <div>
       {this.state.serverResponse}
     </div>
  );
 }
}

если вы пытаетесь сделать запрос post на такие события, как click, то вызовите getData() функция на событии и заменить его содержимое так:

async getData(username, password){
 const res = await axios.post('url-to-post-the-data', {
   username,
   password
 });
 ...
}

кроме того, если вы делаете какой-либо запрос, когда компонент собирается загрузить, просто замените async getData() С async componentDidMount() и измените функцию рендеринга следующим образом:

render(){
 return (
  <div>{this.state.serverResponse}</div>
 )
}