名称: asyncredux-flutter-hooks 描述: 集成AsyncRedux与flutter_hooks包。涵盖添加flutter_hooks_async_redux、使用useSelector钩子,以及将钩子与AsyncRedux状态管理结合。
概述
flutter_hooks_async_redux包提供了一个基于钩子的API来访问AsyncRedux状态。如果您更喜欢使用带有钩子的功能组件,而不是基于小部件的StoreConnector模式,这个包允许您使用像useSelector和useDispatch这样的钩子来与Redux存储交互。
安装
将以下依赖项添加到您的pubspec.yaml中:
dependencies:
flutter_hooks: ^0.21.2
async_redux: ^24.2.2
flutter_hooks_async_redux: ^3.1.0
然后运行flutter pub get。
核心钩子
useSelector
选择状态的一部分并订阅更新。当所选值更改时,小部件会重建:
String username = useSelector<AppState, String>((state) => state.username);
distinct参数(默认为true)控制是否仅当所选值更改时小部件才重建。
创建自定义useAppState钩子
为了方便,可以定义一个预类型为您的状态的自定义钩子:
T useAppState<T>(T Function(AppState state) converter, {bool distinct = true}) =>
useSelector<AppState, T>(converter, distinct: distinct);
这简化了在整个应用中的状态访问:
// 而不是:
String username = useSelector<AppState, String>((state) => state.username);
// 使用:
String username = useAppState((state) => state.username);
useDispatch
分发可能更改存储状态的动作。适用于同步和异步动作:
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
var dispatch = useDispatch();
return ElevatedButton(
onPressed: () => dispatch(IncrementAction()),
child: Text('Increment'),
);
}
}
useDispatchAndWait
分发一个动作并返回一个Future<ActionStatus>,该Future在动作完成时解析:
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
var dispatchAndWait = useDispatchAndWait();
var dispatch = useDispatch();
Future<void> handleSubmit() async {
// 等待第一个动作完成
await dispatchAndWait(DoThisFirstAction());
// 然后分发第二个
dispatch(DoThisSecondAction());
}
return ElevatedButton(
onPressed: handleSubmit,
child: Text('Submit'),
);
}
}
您还可以检查动作状态:
var status = await dispatchAndWait(MyAction());
if (status.isCompletedOk) {
// 动作成功
}
useDispatchSync
强制同步动作分发。如果尝试分发异步动作,则抛出StoreException:
var dispatchSync = useDispatchSync();
dispatchSync(MySyncAction()); // 正常
dispatchSync(MyAsyncAction()); // 抛出StoreException
等待和错误钩子
useIsWaiting
检查异步动作当前是否正在处理中:
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
var dispatch = useDispatch();
var isLoading = useIsWaiting(LoadDataAction);
return Column(
children: [
if (isLoading) CircularProgressIndicator(),
ElevatedButton(
onPressed: () => dispatch(LoadDataAction()),
child: Text('Load'),
),
],
);
}
}
您可以按动作类型、动作实例或多个类型检查:
// 按动作类型
var isWaiting = useIsWaiting(MyAction);
// 按动作实例
var action = MyAction();
dispatch(action);
var isWaiting = useIsWaiting(action);
// 多个类型 - 如果任何在进行中则为true
var isWaiting = useIsWaiting([BuyAction, SellAction]);
useIsFailed
检查动作是否已失败:
var isFailed = useIsFailed(MyAction);
if (isFailed) {
return Text('Something went wrong');
}
useExceptionFor
从失败的动作中检索UserException:
var exception = useExceptionFor(MyAction);
if (exception != null) {
return Text(exception.reason ?? 'Unknown error');
}
useClearExceptionFor
获取一个函数来清除动作的异常状态:
var clearExceptionFor = useClearExceptionFor();
// 当用户解除错误时清除异常
ElevatedButton(
onPressed: () => clearExceptionFor(MyAction),
child: Text('Dismiss'),
)
完整示例
以下是一个结合多个钩子的完整示例:
class UserProfileWidget extends HookWidget {
@override
Widget build(BuildContext context) {
// 选择状态
var username = useAppState((state) => state.user.name);
var email = useAppState((state) => state.user.email);
// 分发钩子
var dispatch = useDispatch();
var dispatchAndWait = useDispatchAndWait();
// 加载和错误状态
var isLoading = useIsWaiting(UpdateProfileAction);
var isFailed = useIsFailed(UpdateProfileAction);
var exception = useExceptionFor(UpdateProfileAction);
var clearException = useClearExceptionFor();
Future<void> handleUpdate() async {
var status = await dispatchAndWait(UpdateProfileAction());
if (status.isCompletedOk) {
// 显示成功消息
}
}
return Column(
children: [
Text('Username: $username'),
Text('Email: $email'),
if (isLoading)
CircularProgressIndicator(),
if (isFailed && exception != null)
Row(
children: [
Text(exception.reason ?? 'Update failed'),
IconButton(
icon: Icon(Icons.close),
onPressed: () => clearException(UpdateProfileAction),
),
],
),
ElevatedButton(
onPressed: isLoading ? null : handleUpdate,
child: Text('Update Profile'),
),
],
);
}
}
钩子参数参考
| 钩子 | 接受 | 返回 |
|---|---|---|
useSelector<St, T> |
转换函数 | 类型为T的选定值 |
useDispatch |
无 | 分发函数 |
useDispatchAndWait |
无 | 返回Future<ActionStatus>的函数 |
useDispatchSync |
无 | 同步分发函数 |
useIsWaiting |
动作类型、实例或类型列表 | bool |
useIsFailed |
动作类型、实例或类型列表 | bool |
useExceptionFor |
动作类型、实例或类型列表 | UserException? |
useClearExceptionFor |
无 | 清除函数 |
钩子与StoreConnector对比
选择钩子当:
- 您更喜欢功能小部件模式
- 您已经在项目中使用
flutter_hooks - 您希望无需视图模型样板就能简洁地访问状态
选择StoreConnector当:
- 您希望UI和状态逻辑之间有明确的分离
- 您需要用于测试的结构化视图模型模式
- 您没有在项目的其他地方使用钩子
两种方法都与AsyncRedux配合良好 - 选择适合您团队偏好的方法。
参考资料
文档中的URL: