2017-10-13 95 views
6

我想在React.js應用程序中使用Async/Await向我的服務器發出一個簡單的請求。 服務器加載在/data一個簡單的JSON它看起來像這樣在React.js中使用Async/Await與Axios

JSON

{ 
    id: 1, 
    name: "Aditya" 
} 

我能夠用簡單的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> 
    ); 
} 
} 

使用這種方法,我得到以下錯誤:

Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

我這不是正確地實現它?

+3

代碼不足。錯誤信息非常清楚。檢查你的渲染方法。 – dfsq

+0

render()工作得很好,因爲我明確提到我可以在使用$ .ajax()時獲取詳細信息。我應該添加哪些額外的代碼?這是使用ES7標準對服務器的簡單獲取請求。 – Aditya

+1

向我們展示你的渲染() –

回答

8

兩個問題跳出來:

  1. getData永遠不會返回任何東西,所以它的諾言(async函數總是返回一個承諾)將與undefined解決時,它解決了

  2. 錯誤信息清楚地表明你試圖直接渲染承諾getData回報,而不是等待它解決,然後渲染分辨率

尋址#1:getData應該調用json的結果:

async getData(){ 
    const res = await axios('/data'); 
    return 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 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> 
     ); 
    } 
} 

進一步更新:您已經指出了在componentDidMount而不是thencatch之間使用await的偏好。你可以通過在其中嵌入一個async IIFE函數並確保函數不會拋出。 (componentDidMount本身不能是async,沒有東西會消耗這個承諾。):

class App extends React.Component{ 
    async getData() { 
     const res = await axios('/data'); 
     return 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> 
     ); 
    } 
} 
+0

它給了我這個錯誤「'這是'super()」之前不允許的。所以我加了super();就在「this.state = {data:null};」之前後來導致一個新的錯誤:「'getData'沒有定義no-undef」 – Aditya

+0

@Morfsys:我不認爲這是確切的錯誤信息。 :-)我確實說過「*像* this這樣的東西」。我已經更新了上面的內容,在'getData'上丟失了'this.'。 –

+0

.catch(err => {/*...handle error ... * /});現在執行。它說res.json()不是一個函數。 – Aditya

2

以我的經驗,在過去的幾個月裏,我已經意識到,要實現這一點的最好辦法是:

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

如果你正試圖使各項活動,例如點擊後要求,然後調用該事件getData()和替換功能的它,像這樣的內容:

async getData(username, password){ 
const res = await axios.post('/data', { 
    username, 
    password 
}); 
... 
} 

此外,如果你做任何請求時,該組件是要加載,然後只需更換async getData()async componentWillMount()並更改渲染功能,如下所示:

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

這基本上只是我的答案,重寫。另外:1.不要使'componentWillMount'成爲'async'函數。 React將忽略返回的承諾。 2.除非'res.data'是一個訪問者返回一個promise,否則在訪問它時使用'await'沒有任何意義。 –

+0

我只是試圖簡化答案。沒有冒犯性,但我認爲'然後'和'catch'並不是遵循諾言的最新標準(ES6)。另外,res.json()不適用於我,所以我不得不用res.data替換它,並在'GET'或'POST'請求​​中附帶承諾。 – Aditya

+0

'then'和'catch' **是ES2015(又名「ES6」)處理承諾的方式。 'async' /'await'是ES2017(「ES8」)的方式。但是你只能在'async'函數中使用'await',並且使'componentWillMount'' async'創建一個永遠不會被使用的promise。如果你想使用'await'來代替,那很好,但是你會這樣做,不同於''componentWillMount'上的'async'。無論如何,坦率地說,兩個月後回來,發佈一個只是調整現有的沒有歸屬的答案並不酷。 –