Blog.

旧调新弹 - 使用 use 来获取数据

LiuuY

如果你问我:React 使用什么方式获取数据?我的回答是:用第三方库,例如 SWR 或者 React Query 之类的,再或者使用第三方框架自带的机制,例如 Remix Loader

难道 React 没有自带的数据获取方式么?useEffect 不行么?

不太行,使用 useEffect 获取数据异常的麻烦,你需要:

  1. 处理成功、失败和 Loading 状态。
const [data, setData] = useState()
const [error, setError] = useState()
const [isLoading, setIsLoading] = useState()

同时,往往还需要在成功设置数据时,清空 error,反之亦然。

  1. 处理 Race Condition

  2. 区分空数据和初始数据。

const [data, setData] = useState([])

如果数据是一个列表,将初始值设置为空数组([]),那将如何区分返回的空数据,还是初始值呢?往往此事,我们需要将初始值设置为 undefined

  1. 处理 useEffect触发两次问题。

一个「简单」的使用 useEffect 获取数据的代码如下:

这也就是为什么第三方数据获取库大行其道的重要原因,因为它们极大的简化了逻辑,同时也包含了 CachePrefetchingMiddleware 等等常用的功能:

不过现在 React 团队推出了一个新的 Hook:use

它结合 SuspenceError Boundary 可以非常简单明了的处理成功、失败和 loading 状态。

同时也没有 Race Condition 等等问题。

  1. 我们可以把获取数据的 Promise 传入到 use 中,返回值就是 Promise 的 resolve 值,类似于 await一般
const data = use(dataPromise); 
// 后续处理逻辑

// 类似
const data = await dataPromise;
// 后续处理逻辑
  1. 使用 Suspence 处理 Loading 状态; 使用 Error Boundary 处理 Error 状态。
  1. 也可以使用 Promise.catch 处理 Error 状态。

可以看到和上面 useEffect 的代码相比简化了非常多。

同时,一个 useEffect 和很多第三方库还无法完成的功能:use 也可以在 Server Components 和 Client Components 之间传递数据

总结

不使用第三方库获取数据一直是一个老大难问题,现在我们可以考虑使用 use,这也算第一个官方的「原生」获取数据方法。但是 use 并没有包含其他的高级功能:CachePrefetchingMiddleware 等等在数据获取,或者可以称之为异步数据管理这个问题所必须的功能。