首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用异步componentDidMount()好吗?

使用异步componentDidMount()好吗?
EN

Stack Overflow用户
提问于 2017-12-25 16:19:40
回答 9查看 126.6K关注 0票数 196

使用componentDidMount()作为异步函数是否是反应本地的良好实践,还是我应该避免它?

当组件挂载时,我需要从AsyncStorage获得一些信息,但我所知道的唯一可能的方法是使componentDidMount()函数异步。

代码语言:javascript
复制
async componentDidMount() {
    let auth = await this.getAuth();
    if (auth) 
        this.checkAuth(auth);
}

这个问题有什么问题吗?还有其他解决办法吗?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2017-12-25 17:46:58

让我们首先指出不同之处,并确定它是如何引起麻烦的。

下面是异步和“同步”componentDidMount()生命周期方法的代码:

代码语言:javascript
复制
// This is typescript code
componentDidMount(): void { /* do something */ }

async componentDidMount(): Promise<void> {
    /* do something */
    /* You can use "await" here */
}

通过查看代码,我可以指出以下不同之处:

  1. async关键字:在类型记录中,这只是一个代码标记。它做了两件事:
    • 强制返回类型为Promise<void>而不是void。如果您显式地指定返回类型为不承诺(例如:无效),类型记录将向您吐出一个错误。
    • 允许在方法中使用await关键字。

  1. 返回类型从void更改为Promise<void>
    • 这意味着您现在可以这样做: async someMethod(): Promise<void> { await componentDidMount(); }

  1. 现在,您可以在方法中使用await关键字,并暂时暂停其执行。类似于这样:异步componentDidMount():承诺{ const用户=等待axios.get(“http://localhost:9001/users"”);const问题=等待axios.get(“http://localhost:9001/questions"”);//睡眠10秒等待新的承诺(resolve => { setTimeout(resolve,10000);});//这一行代码将在10+秒this.setState({ users,问题})之后执行;返回Promise.resolve();}

,现在,他们怎么能制造麻烦呢?

  1. async关键字是绝对无害的。
  2. 我无法想象需要调用componentDidMount()方法的任何情况,因此返回类型Promise<void>也是无害的。 调用具有Promise<void>返回类型而不带await关键字的方法与调用具有void返回类型的方法没有任何区别。
  3. 由于在componentDidMount()之后没有生命周期方法,延迟执行它似乎是非常安全的。但还是有个问题。 比如说,上面的this.setState({users, questions});将在10秒后执行。在拖延时间的中间,另一个..。 this.setState({users: newerUsers, questions: newerQuestions}); ..。已成功执行并更新了DOM。结果对用户是可见的。时钟继续滴答作响,10秒过去了。延迟的this.setState(...)然后将执行,DOM将再次更新,这一时间与老用户和老问题。结果对用户也是可见的。

=> --使用asynccomponentDidMount()方法是非常安全的(我不确定大约100%)。我是它的忠实粉丝,到目前为止,我还没有遇到任何让我头疼的问题。

票数 200
EN

Stack Overflow用户

发布于 2019-06-28 03:08:46

更新2020年4月:问题似乎在最新的反应16.13.1中得到了解决,见这个沙箱例子。感谢@abernier指出这一点。

我做了一些研究,并发现了一个重要的区别:React不会处理来自异步生命周期方法的错误。

所以,如果你写这样的东西:

代码语言:javascript
复制
componentDidMount()
{
    throw new Error('I crashed!');
}

然后您的错误将被误差边界捕获,您可以处理它并显示一条优美的消息。

如果我们像这样修改代码:

代码语言:javascript
复制
async componentDidMount()
{
    throw new Error('I crashed!');
}

这相当于:

代码语言:javascript
复制
componentDidMount()
{
    return Promise.reject(new Error('I crashed!'));
}

然后,您的错误将被默默吞下。为你感到羞耻,反应..。

那么,我们如何处理错误比呢?唯一的办法似乎是这样明确地抓到:

代码语言:javascript
复制
async componentDidMount()
{
    try
    {
         await myAsyncFunction();
    }
    catch(error)
    {
        //...
    }
}

或者像这样:

代码语言:javascript
复制
componentDidMount()
{
    myAsyncFunction()
    .catch(()=>
    {
        //...
    });
}

如果我们仍然希望我们的错误达到错误边界,我可以考虑以下技巧:

  1. 捕获错误,使错误处理程序更改组件状态。
  2. 如果状态指示错误,则从render方法抛出它。

示例:

代码语言:javascript
复制
class BuggyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
  }
  
  buggyAsyncfunction() { return Promise.reject(new Error('I crashed async!'));}
  
  async componentDidMount() {
    try
    {
      await this.buggyAsyncfunction();
    }
    catch(error)
    {
        this.setState({error: error});
    }
  }
  
  render() {
    if(this.state.error)
        throw this.state.error;
        
    return <h1>I am OK</h1>;
  }
}
票数 34
EN

Stack Overflow用户

发布于 2017-12-25 16:33:28

您的代码很好,而且对我来说非常可读的。看看这个戴尔·杰斐逊的文章,他在这里展示了一个异步componentDidMount示例,而且看起来也很不错。

但是,有些人会说,一个阅读代码的人可能会假设,React会做一些与返回的承诺有关的事情。

因此,对这个代码的解释以及它是否是一个好的实践都是非常个人化的。

如果您想要另一个解决方案,可以使用承诺。例如:

代码语言:javascript
复制
componentDidMount() {
    fetch(this.getAuth())
      .then(auth => {
          if (auth) this.checkAuth(auth)
      })
}
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47970276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档