Используйте 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>
)
}