`useEffect()` 和 `async`
如果您已经学习了传统的基于类的 React 组件,并且现在正尝试转向 Hooks,那么在此过程中可能会有一些事情让您感到困惑。
对我来说,需要花点功夫去研究的一个东西就是- 本质上是、和- 和/ 的useEffect()
替代品的组合。componentDidMount
componentDidUpdate
componentWillUnmount
async
await
现状
常见场景:我们的应用加载完毕,屏幕上显示了一些内容,然后我们想要获取一些数据。我们不想因为 API 调用耗时过长而阻碍用户继续操作,或者让他们盯着空白屏幕。
componentDidMount
如果使用基于 React 类的组件,这就是我们解决这个问题的方法。它确保首先将实际的组件插入到 DOM 树中,然后再render()
调用。
如果我们不需要发出 API 请求,那么组件将直接渲染到屏幕上。如果我们确实需要发出 API 请求,则应该在 内部进行componentDidMount()
。此外,如果在收到 API 响应后我们必须更新 或setState()
,那么这实际上会触发第二次渲染。
那么调用将会是这样的:
- 组件挂载()
- 使成为()
- setState() [来自 componentDidMount() 内部]
- 使成为()
即使进行了二次渲染,React 文档也指出用户不会看到中间状态。所以没有奇怪的闪烁 UI——这对我们来说是好事!然而,文档也建议谨慎使用,因为这种方式可能会导致性能问题。
更具体地说,任何需要插入树的 DOM 节点都属于这个位置,componentDidMount()
即 。如果可以的话,React 建议state
在 中constructor()
而不是此处进行初始化。显然,这并不总是可行的,但这是他们的建议。
// src/api/index.js
export default {
async index() {
const res = await fetch('https://my-json-server.typicode.com/Claim-Academy-JS/products/products')
return await res.json()
}
}
/* ------------------ */
import api from 'api'
async componentDidMount() {
const products = await api.index()
this.setState({ filteredProducts: products, products })
}
这段代码展示了内部进行的 fetch 调用componentDidMount()
,在本例中,对于我的项目,我需要进行这样的设置。这些产品需要插入到 DOM 树中,所以我进行了 fetch 调用并设置了状态。当然,async
这两者都在componentDidMount()
以及我导出的对象的index()
方法上进行。然后在这两个方法中,我们得到await
了结果。
useEffect()
现在有了 Hooks,更具体地说useEffect()
,我们需要注意几件事。首先,我们必须理解useEffect()
需要两个参数。
第一个参数
- 回调函数
第二个论点
- 监视属性的变化 -> 然后触发提供的回调
因此,像往常一样,需要一个回调函数——这并不奇怪。如果我们忘记指定第二个参数,它可能会导致一些问题。如果没有提供第二个参数,useEffect()
则无论更新什么,每次更新都会触发回调函数。此外,如果函数内部使用了setState()
或setter 方法,回调函数就会陷入无限循环。useState()
useEffect()
让我们看一下与前面的示例等效的代码,只是使用了useEffect()
:
useEffect(() => {
(async () => {
const products = await api.index()
setFilteredProducts(products)
setProducts(products)
})()
}, [])
这次你会看到里面有一个立即调用函数表达式(IIFE)。我们也可以给这个函数命名,然后在里面直接调用它。
useEffect(() => {
const fetchProducts = async () => {
const products = await api.index()
setFilteredProducts(products)
setProducts(products)
}
fetchProducts()
}, [])
还要注意,我们实际上提供了一个回调函数,useEffect()
并且必须在该回调函数中定义另一个函数并调用它。这是因为 fetch 调用返回了一个 Promise。因此,它useEffect()
本身并不负责处理这个问题,而是由我们定义的函数来处理。
最后,第二个参数用于确保它useEffect()
仅在特定时间运行。
我们在这里提供了[]
第二个参数。这表示useEffect()
“嘿,我只希望你在这个组件首次挂载时运行你的回调,仅此而已。” 通过使用,[]
我们告知useEffect()
你没有需要监视的属性,然后在这些属性发生变化时运行你的回调。只需运行一次。
[]
作为第二个参数和没有第二个参数之间也有区别。如前所述,没有第二个参数时,它useEffect()
会认为它应该在组件挂载时运行,然后在之后的每次更新时运行,无论状态发生什么变化。
如果我们希望每次特定状态发生变化时运行一个函数,您只需将其放在括号内,就像这样[somePropertyNameHere]
。
文章将被卸载
useEffect()
我花了些时间才找到将和函数组合起来的方法async
。令人惊讶的是,React 文档中根本没有关于这种情况的示例。我参考了几篇解释此问题的不同第三方文章,以确保我的思路正确。Robin Wieruch 写了一篇相关文章;这是我找到的第一篇关于这个主题的文章,也是比较好的文章之一。
非常高兴能够解决这个问题,因为尽管这是一个很奇怪的问题 - 但我仍然更喜欢 Hooks!
鏂囩珷鏉ユ簮锛�https://dev.to/stlnick/useeffect-and-async-4da8