性能
Quaere 在各种 web 应用中提供了关键功能,因此 性能 是重中之重。
Quaere 内置的 缓存 和 重复数据删除 会跳过不必要的网络请求,但 useQuery
hook 本身的性能仍然很重要。在一个复杂的应用中,单个页面渲染可能会调用数百次 useQuery
。
Quaere 确保你的应用具有:
- 没有不必要的请求
- 没有不必要的重新渲染
- 没有不必要的代码导入
而无需你更改任何代码。
重复数据删除
在应用中重用 Quaere hooks 非常常见。例如,一个应用渲染 5 次当前用户的头像:
function Avatar() {
const { data, error } = useQuery({ query: userQuery });
if (error) return <Error />;
if (!data) return <Spinner />;
return <img src={data.avatar_url} />;
}
function App() {
return (
<>
<Avatar />
<Avatar />
<Avatar />
<Avatar />
<Avatar />
</>
);
}
每个 <Avatar>
组件内部都有一个 useQuery
hook。由于它们具有相同的 Quaere key,并且几乎同时渲染,因此 只会发送 1 个网络请求。
你可以在任何地方重用数据 hooks(比如上面示例中的 useUser
),而不用担心性能或重复请求。
还有一个 staleTime
选项用于覆盖默认的数据被视为过期的毫秒数。
深度比较
Quaere 默认 深度比较 数据更改。如果 data
值没有改变,则不会触发重新渲染。
依赖收集
useQuery
返回 4 个 有状态的 值:data
、error
、isLoading
和 isFetching
,每个都可以独立更新。例如,如果我们在一个完整的数据请求生命周期中打印这些值,则将如下所示:
function App() {
const { data, error, isLoading, isFetching } = useQuery({ query: userQuery });
console.log(data, error, isLoading, isFetching);
return null;
}
在最坏的情况下(第一个请求失败,然后重试成功),你将看到 4 行日志:
// console.log(data, error, isLoading, isFetching)
undefined undefined true true // => 开始 fetching
undefined Error false false // => 结束 fetching,出现错误
undefined Error true true // => 开始重试
Data undefined false false // => 重试结束,得到数据
状态的改变是有道理的。但这也意味着组件 渲染了 4 次。
如果我们将组件更改为只使用 data
:
function App() {
const { data } = useQuery({ query: userQuery });
console.log(data);
return null;
}
神奇的事情发生了 - 现在只有 2 次重新渲染:
// console.log(data)
undefined; // => hydration / 初始渲染
Data; // => 重试结束,得到数据
内部发生了完全相同的过程,第一个请求出现了错误,然后我们重试得到了数据。但是,Quaere 只更新了组件使用的状态,即:data
。
Tree Shaking
Quaere 满足 tree-shakeable (opens in a new tab) 且没有副作用。这意味着如果你只导入核心的 useQuery
API,像 useMutation
这样的未使用的 API 将不会绑定到你的应用中。