| Crates.io | leptos-query-rs |
| lib.rs | leptos-query-rs |
| version | 0.5.1 |
| created_at | 2025-09-01 10:03:26.873096+00 |
| updated_at | 2025-09-07 08:30:08.289874+00 |
| description | A powerful, type-safe data fetching and caching library for Leptos 0.8 applications |
| homepage | |
| repository | https://github.com/cloud-shuttle/leptos-query-rs |
| max_upload_size | |
| id | 1819380 |
| size | 1,116,758 |
A React Query inspired data fetching library for Leptos applications, providing powerful caching, background updates, and error handling capabilities.
🚀 Now fully compatible with Leptos 0.8!
Add to your Cargo.toml:
[dependencies]
leptos-query = "0.4.0"
leptos = "0.8"
serde = { version = "1.0", features = ["derive"] }
use leptos::*;
use leptos_query::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
async fn fetch_user(id: u32) -> Result<User, QueryError> {
// Your async function here
Ok(User {
id,
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
})
}
#[component]
fn UserProfile(user_id: u32) -> impl IntoView {
let user_query = use_query(
move || QueryKey::new(&["user", &user_id.to_string()]),
move || async move { fetch_user(user_id).await },
QueryOptions::default(),
);
view! {
<div>
{move || match user_query.data.get() {
Some(user) => view! { <div>"User: " {user.name}</div> },
None if user_query.is_loading.get() => view! { <div>"Loading..."</div> },
None => view! { <div>"No user found"</div> },
}}
</div>
}
}
Wrap your app with the QueryClientProvider:
#[component]
fn App() -> impl IntoView {
view! {
<QueryClientProvider>
<UserProfile user_id=1/>
</QueryClientProvider>
}
}
pub fn use_query<T, F, Fut>(
key_fn: F,
query_fn: impl Fn() -> Fut + Clone + Send + Sync + 'static,
options: QueryOptions,
) -> QueryResult<T>
Parameters:
key_fn: Function that returns a QueryKey for cachingquery_fn: Async function that fetches the dataoptions: Configuration options for the queryReturns:
QueryResult<T>: Object containing data, loading state, and actionslet options = QueryOptions::default()
.with_stale_time(Duration::from_secs(60))
.with_cache_time(Duration::from_secs(300))
.with_refetch_interval(Duration::from_secs(30));
pub struct QueryResult<T> {
pub data: Signal<Option<T>>, // The query data
pub error: Signal<Option<QueryError>>, // Error if any
pub is_loading: Signal<bool>, // Whether loading
pub is_success: Signal<bool>, // Whether succeeded
pub is_error: Signal<bool>, // Whether failed
pub status: Signal<QueryStatus>, // Current status
pub refetch: Callback<()>, // Refetch function
}
pub fn use_mutation<TData, TError, TVariables, F, Fut>(
mutation_fn: F,
options: MutationOptions,
) -> MutationResult<TData, TError, TVariables>
Example:
async fn create_user(user: CreateUserRequest) -> Result<User, QueryError> {
// Your mutation logic here
Ok(User { /* ... */ })
}
let mutation = use_mutation(
create_user,
MutationOptions::default()
.invalidate_queries(vec![QueryKeyPattern::Exact(QueryKey::from("users"))]),
);
// Execute mutation
mutation.mutate.call(CreateUserRequest { /* ... */ });
The library provides comprehensive error handling:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum QueryError {
NetworkError(String),
SerializationError(String),
DeserializationError(String),
TimeoutError(String),
GenericError(String),
}
let retry_config = RetryConfig::new(3, Duration::from_secs(1))
.with_max_delay(Duration::from_secs(30))
.with_fixed_delay()
.no_network_retry();
Query keys are used for caching and invalidation:
// Simple key
QueryKey::from("users")
// Compound key
QueryKey::from(["users", user_id.to_string()])
// With parameters
QueryKey::from_parts(&[user_id, filter]).unwrap()
// Invalidate specific queries
client.remove_query(&QueryKey::from("users"));
// Invalidate by pattern
client.invalidate_queries(&QueryKeyPattern::Prefix(QueryKey::from("users")));
let options = QueryOptions::default()
.with_refetch_interval(Duration::from_secs(30));
See the examples/ directory for complete working examples:
basic.rs: Basic query usagemutations.rs: Mutation examplescaching.rs: Advanced caching examplesContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.