以下
reactでaxiosでasync/awaitを使用する方法
React.jsアプリでAsync/Awaitを使用して、サーバーに単純なgetリクエストを作成しようとしています。サーバーは次のような/data
に単純なJSONをロードします
JSON
{
id: 1,
name: "Aditya"
}
単純なjquery ajax getメソッドを使用して、Reactアプリにデータを取得できます。ただし、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子としては無効です(見つかった:[object Promise])。子のコレクションをレンダリングする場合は、代わりに配列を使用します。
正しく実装していませんか?
2つの問題が飛び出します。
getData
は何も返さないため、そのプロミス(async
関数は常にプロミスを返します)は、解決時にundefined
で解決されます
エラーメッセージは、解決するのを待ってから解決をレンダリングするのではなく、promise getData
リターンを直接レンダリングしようとしていることを明確に示しています。
アドレス指定#1:getData
は、json
を呼び出した結果をreturn返します:
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関数をその中に入れ子にして、関数がスローできないようにします。 (componentDidMount
自体を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>
);
}
}
クリックなどのイベントでポストリクエストを行おうとしている場合は、イベントで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>
)
}