A hook that manages the state of an asynchronous operation with loading, data, and error states.
import 'package:flutter_use/flutter_use.dart';
class UserProfile extends HookWidget {
final String userId;
const UserProfile({required this.userId});
@override
Widget build(BuildContext context) {
final userState = useAsync(
() => fetchUserData(userId),
keys: [userId], // Re-fetch when userId changes
);
if (userState.loading) {
return const CircularProgressIndicator();
}
if (userState.hasError) {
return Text('Error: ${userState.error}');
}
if (userState.hasData) {
return UserCard(user: userState.data!);
}
return const SizedBox();
}
}A variant that doesn't execute automatically and provides manual control:
class LoginForm extends HookWidget {
@override
Widget build(BuildContext context) {
final loginAction = useAsyncFn(() async {
return await authService.login(email, password);
});
return Column(
children: [
// Form fields...
ElevatedButton(
onPressed: loginAction.loading
? null
: () async {
try {
final user = await loginAction.execute();
Navigator.pushReplacementNamed(context, '/home');
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login failed: $e')),
);
}
},
child: loginAction.loading
? const CircularProgressIndicator()
: const Text('Login'),
),
],
);
}
}AsyncState<T> useAsync<T>(
Future<T> Function() asyncFunction, {
List<Object?> keys = const [],
})Parameters:
asyncFunction: The async function to executekeys: Dependencies that trigger re-execution when changed
Returns: AsyncState<T> with:
loading: Whether the operation is in progressdata: The result data if successfulerror: The error if failedhasData: Whether data is availablehasError: Whether an error occurred
AsyncAction<T> useAsyncFn<T>(
Future<T> Function() asyncFunction,
)Parameters:
asyncFunction: The async function to execute on demand
Returns: AsyncAction<T> with:
- All properties from
AsyncState<T> execute(): Function to trigger the async operation
- Automatic loading state management
- Error handling
- Dependency tracking for re-execution
- Cancellation of previous operations
- Type-safe data handling
- Manual execution control with
useAsyncFn
-
API Data Fetching
final productsState = useAsync(() => api.getProducts());
-
User Authentication
final authAction = useAsyncFn(() => auth.signIn(credentials));
-
File Operations
final fileState = useAsync(() => loadFileContent(path));
-
Real-time Data
final liveData = useAsync( () => streamToFuture(dataStream), keys: [refreshTrigger], );