Async state,
solved
gpui-query brings TanStack Query's caching, retries, and background revalidation to Rust — purpose-built for GPUI, the framework behind Zed.
use gpui_query::prelude::*;
let users = use_query(cx, "users", || async {
fetch_users().await
});
match &users.data {
Some(list) => render_list(list),
None => render_loading(),
} // caching, retry, dedup — handledGET /users · in flight
// capabilities
Everything the fetch deserves
The full TanStack Query feature set, rebuilt around GPUI's entity and async model.
Declarative Queries
One hook. gpui-query handles fetching, caching, and state updates so your render code stays a pure function of data.
Smart Caching
Cache policies for every use case — pick one per query and move on.
Mutations
First-class mutation support with success and error callbacks, plus optimistic updates that roll back on failure.
Infinite Queries
Paginate effortlessly with built-in infinite query support and bidirectional fetching.
Cancellation
Signal-checked retries and cooperative cancellation for a clean async lifecycle — no orphaned tasks.
Persistence
Serialize and restore query state across launches with custom persistence backends.
// get started
Up and running in 30 seconds
- 01
Add the dependency
One cargo command, zero configuration.
- 02
Write your first query
Call use_query with a key and an async fetcher.
- 03
Done
Caching, retry, and deduplication are automatic.
use gpui_query::prelude::*;
fn render_user_list(cx: &mut ViewContext<App>) -> impl IntoElement {
let query = use_query(cx, "user-list", || async {
fetch_users().await
});
div().children(match &query.data {
Some(users) => users.iter().map(render_user),
None => vec![div().child("Loading...")],
})
}// comparison
Why gpui-query?
See how gpui-query compares to hand-rolling async state in GPUI.
| Feature | gpui-query | cx.spawn() | Raw Futures |
|---|---|---|---|
| Caching | |||
| Auto Retry | |||
| Deduplication | |||
| Cache Policies | |||
| DevTools | |||
| Persistence | |||
| Type Safety | |||
| No Setup Required | |||
| Zero Dependencies |
// architecture
Three layers, one direction
Each layer has a single responsibility. Data flows down, results flow back up.
Hook Layer
use_query / use_mutation / use_infinite_query
Client Layer
QueryClient / Registry / GC
Core Layer
QueryResource / CachePolicy / QueryKey
// ship it
Stop hand-rolling async state
One dependency away from caching, retries, and revalidation in your GPUI app.