useFetch()
当 Endpoint 不在缓存中或已过时时获取它。返回一个可与
React.use() 配合使用的 thenable——use(useFetch(endpoint, args)) 的行为与 useSuspense() 相同:数据加载时挂起,数据可用时返回反规范化数据,并在失效时重新挂起。
用法
并行加载数据
由于 useFetch() 和 use() 是分开调用的,多个获取会并行开始——即使第一个 use() 挂起也是如此。请参阅下方的并行获取示例。
Resources
PostWithComments
import { use } from 'react'; import { useFetch } from '@data-client/react'; import { PostResource, CommentResource } from './Resources'; function PostWithComments({ id }: { id: number }) { // Both fetches start in parallel const postPromise = useFetch(PostResource.get, { id }); const commentsPromise = useFetch(CommentResource.getList, { postId: id, }); // use() reads the results — if the first suspends, // the second fetch is already in-flight const post = use(postPromise); const comments = use(commentsPromise); return ( <article> <h3>{post.title}</h3> <p>{post.body}</p> <h4>Comments</h4> {comments.map(comment => ( <div key={comment.id} className="listItem"> <strong>{comment.author}</strong>: {comment.text} </div> ))} </article> ); } render(<PostWithComments id={1} />);
结果
Store▶
预取
useFetch() 也可以单独使用,在渲染树的较早位置确保资源在需要之前就已可用。
提示
在另一个组件中与数据绑定 hook(useCache()、useSuspense()、useDLE()、useLive())结合使用。
import { useFetch } from '@data-client/react';
import { PostResource } from './resources/Post';
function MasterPost({ id }: { id: number }) {
useFetch(PostResource.get, { id });
// ...
}
行为
| 过期状态 | 获取 | use() 行为 | resolved | 条件 |
|---|---|---|---|---|
| Invalid | 是1 | 挂起 | false | 不在 store 中、删除、失效 |
| Stale | 是1 | 挂起 | false | (首次渲染、参数变化)且 过期时间 < 当前时间 |
| Valid | 否 | 返回数据 | true | 获取完成 |
| Error | 否 | 抛出错误 | true | 获取失败,由 Error Boundary 捕获 |
| 否 | undefined | 第二个参数为 null |
当 store 更新时(例如通过变更或 Controller.set()),组件会重新渲染,useFetch() 会自动返回更新后的反规范化数据。
备注
- 相同的获取会自动去重
React Native
使用 React Navigation 时,如果数据被视为过时,useFetch() 会在获得焦点时触发获取。
条件依赖
将 null 作为任意 Data Client hook 的第二个参数,表示“什么都不做”。
// todo could be undefined if id is undefined
const todo = useFetch(TodoResource.get, id ? { id } : null);
类型
- 类型
- 使用泛型
function useFetch(
endpoint: ReadEndpoint,
...args: Parameters<typeof endpoint> | [null]
): (PromiseLike<any> & { resolved: boolean }) | undefined;
function useFetch<
E extends EndpointInterface<
FetchFunction,
Schema | undefined,
undefined
>,
Args extends readonly [...Parameters<E>] | readonly [null],
>(endpoint: E, ...args: Args): UsablePromise<Denormalize<E['schema']>>;
示例
检查获取状态
使用 promise.resolved 检查数据是否仍在加载:
import { useFetch } from '@data-client/react';
import { PostResource } from './resources/Post';
function MasterPost({ id }: { id: number }) {
const promise = useFetch(PostResource.get, { id });
if (!promise.resolved) {
// fetch is in-flight
}
// ...
}
NextJS 预加载
为了避免 NextJS 中的获取瀑布,有时你可能需要为顶层路由添加预加载。