Query
The @SolidQuery() annotation allows you to create reactive state based on asynchronous data sources, such as fetching data from a network.
class QueryExample extends StatelessWidget { const QueryExample({super.key});
@SolidQuery() Future<String> fetchData() async { await Future.delayed(const Duration(seconds: 1)); return 'Fetched Data'; }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Query')), body: Center( child: fetchData().when( ready: (data) => Text(data), loading: () => CircularProgressIndicator(), error: (error, stackTrace) => Text('Error: $error'), ), ), ); }}This example defines a fetchData method annotated with @SolidQuery(), which simulates fetching data asynchronously.
The when method is used to handle the build different widgets based on the states of the query: ready, loading, and error.
You can also use the @SolidQuery() annotation for streams.
@SolidQuery()Stream<int> fetchData() { return Stream.periodic(const Duration(seconds: 1), (i) => i);}And magically, you don’t have to change anything else.
Reacting to state
Section titled “Reacting to state”A query can also depend on reactive state variables.
class QueryWithSourceExample extends StatelessWidget { QueryWithSourceExample({super.key});
@SolidState() String? userId;
@SolidQuery(debounce: Duration(seconds: 1)) Future<String?> fetchData() async { if (userId == null) return null; await Future.delayed(const Duration(seconds: 1)); return 'Fetched Data for $userId'; }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('QueryWithSource')), body: Center( child: fetchData().when( ready: (data) { if (data == null) { return const Text('No user ID provided'); } return Text(data); }, loading: () => CircularProgressIndicator(), error: (error, stackTrace) => Text('Error: $error'), ), ), floatingActionButton: FloatingActionButton( onPressed: () => userId = 'user_${DateTime.now().millisecondsSinceEpoch}', child: const Icon(Icons.refresh), ), ); }}Detect if a query is refreshing
Section titled “Detect if a query is refreshing”By default, when a query is re-executed due to a dependency change, it doesn’t enter the loading state again. Instead, it stays in the current state while the new data is being fetched. When the new data arrives, the state updates accordingly. This behavior is designed to provide a smoother user experience by avoiding unnecessary loading indicators during data refreshes.
You can detect if a query is currently refreshing by using the isRefreshing property.
fetchData().isRefreshingThis property returns true if the query is in the process of refreshing its data, allowing you to adjust your UI accordingly (e.g., showing a subtle loading indicator or a refresh icon).
You can disable this behavior by setting the useRefreshing parameter to false in the @SolidQuery() annotation.
@SolidQuery(useRefreshing: false)In this case, the query will enter the loading state again when it is re-executed due to a dependency change.
Manually refreshing a query
Section titled “Manually refreshing a query”You can manually refresh a query by calling the refresh method on it.
fetchData.refresh();