Используйте 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 ответов
выскакивают два вопроса:
код
getData
никогда ничего не возвращает, поэтому его обещание (async
функции всегда возвращают обещание) разрешат сundefined
при разрешениисообщение об ошибке ясно показывает, что вы пытаетесь напрямую отобразить обещание
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>
)
}