2017-10-13 96 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'。无论如何,坦率地说,两个月后回来,发布一个只是调整现有的没有归属的答案并不酷。 –