Reactjs 使用async componentDidMount()好吗?
在React Native中使用Reactjs 使用async componentDidMount()好吗?,reactjs,asynchronous,react-native,Reactjs,Asynchronous,React Native,在React Native中使用componentDidMount()作为异步函数是一种很好的做法,还是应该避免 当组件装入时,我需要从AsyncStorage获取一些信息,但我知道的唯一方法是使componentDidMount()函数异步 async componentDidMount() { let auth = await this.getAuth(); if (auth) this.checkAuth(auth); } 这有什么问题吗?还有其他解决方
componentDidMount()
作为异步函数是一种很好的做法,还是应该避免
当组件装入时,我需要从AsyncStorage
获取一些信息,但我知道的唯一方法是使componentDidMount()
函数异步
async componentDidMount() {
let auth = await this.getAuth();
if (auth)
this.checkAuth(auth);
}
这有什么问题吗?还有其他解决方案吗?您的代码很好,对我来说非常可读。在这里,他展示了一个async
componentDidMount
示例,看起来也很不错
但是有些人会说,阅读代码的人可能会认为React使用返回的承诺做了一些事情
因此,对这一准则的解释,以及它是否是一种良好的做法,是非常个人化的
如果您需要其他解决方案,可以使用。例如:
componentDidMount() {
fetch(this.getAuth())
.then(auth => {
if (auth) this.checkAuth(auth)
})
}
让我们从指出差异开始,并确定它如何会造成麻烦 下面是异步和“sync”的代码
componentDidMount()
life-cycle方法:
// This is typescript code
componentDidMount(): void { /* do something */ }
async componentDidMount(): Promise<void> {
/* do something */
/* You can use "await" here */
}
现在,他们怎么会制造麻烦呢?
async
关键字绝对无害componentDidMount()
方法,因此返回类型Promise
也是无害的
调用返回类型为Promise
而不使用wait
关键字的方法与调用返回类型为void
的方法没有区别componentDidMount()
之后没有生命周期方法,因此延迟其执行似乎相当安全。但是有一个问题
比方说,上面的this.setState({users,questions})代码>将在10秒后执行。在延迟时间的中间,另一个…
this.setState({users:newerUsers,questions:newerQuestions})代码>
。。。已成功执行,并且已更新DOM。结果对用户可见。时钟继续滴答作响,10秒过去了。然后将执行延迟的this.setState(…)
,DOM将再次更新,这一次将使用老用户和老问题。结果也将对用户可见
async
和componentDidMount()
方法是非常安全的(我不确定大约100%)。我是它的忠实粉丝,到目前为止,我还没有遇到任何让我头疼的问题。更新:
(我的身材:React 16,网页4,巴别塔7):
使用Babel 7时,您会发现:
使用此模式
async componentDidMount() {
try {
const res = await fetch(config.discover.url);
const data = await res.json();
console.log(data);
} catch(e) {
console.error(e);
}
}
componentDidMount() {
fetch(config.discover.url)
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
}
您将遇到以下错误
未捕获引用错误:未定义regeneratorRuntime
在这种情况下,您需要安装babel插件转换运行时
如果出于某种原因,您不希望安装上述软件包(babel插件转换运行时),那么您将希望坚持承诺模式
async componentDidMount() {
try {
const res = await fetch(config.discover.url);
const data = await res.json();
console.log(data);
} catch(e) {
console.error(e);
}
}
componentDidMount() {
fetch(config.discover.url)
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
}
当您使用
componentDidMount
而不使用async
关键字时,文档会这样说:
您可以在componentDidMount()中立即调用setState()。它将触发额外的渲染,但会在浏览器更新屏幕之前发生
如果使用
async componentDidMount
将失去此功能:在浏览器更新屏幕后将发生另一次渲染。但是,在我看来,如果您正在考虑使用异步,例如获取数据,则无法避免浏览器会更新屏幕两次。在另一个世界中,在浏览器更新屏幕之前暂停componentDidMount是不可能的我认为只要您知道自己在做什么就可以了。但这可能会让人困惑,因为async componentDidMount()
在componentWillUnmount
运行并且该组件已卸载后仍然可以运行
您可能还希望在componentDidMount
中启动同步和异步任务。如果componentDidMount
是异步的,则必须将所有同步代码放在第一个wait
之前。对于某些人来说,第一个wait
之前的代码是否同步运行可能并不明显。在这种情况下,我可能会保持componentDidMount
同步,但让它调用sync和async方法
无论您选择
async componentDidMount(),ComponentDidMount中的异步加载是一种推荐的设计模式,因为React从传统的生命周期方法(componentWillMount、componentWillReceiveProps、componentWillUpdate)转移到异步呈现
这篇博文非常有助于解释为什么这是安全的,并提供了ComponentDidMount中异步加载的示例:
2020年4月更新:
最新的React 16.13.1中似乎解决了该问题,请参阅。感谢@abernier指出这一点
我做了一些研究,发现了一个重要的区别:
React不处理来自异步生命周期方法的错误。
所以,如果你写这样的东西:
componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
然后您的错误将被捕获,您可以处理它并显示一条优美的消息
如果我们像这样更改代码:
componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
这相当于:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
然后您的错误将被默默地吞没。你真丢脸,反应
那么,我们如何处理错误呢?唯一的方法似乎是这样的明确捕获:
componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
或者像这样:
componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
throw new Error('I crashed!');
}
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
如果我们仍然希望误差达到误差边界,我可以考虑以下技巧:
捕获错误,使错误处理程序更改组件状态
如果状态指示错误