AsyncRedux与FlutterHooks集成技能Skill asyncredux-flutter-hooks

这个技能用于在Flutter移动应用开发中,通过`flutter_hooks_async_redux`包集成AsyncRedux状态管理与Flutter Hooks,提供useSelector、useDispatch等钩子来实现状态访问和动作分发,简化功能组件的开发,提升代码效率和可维护性。关键词:Flutter, AsyncRedux, Hooks, 状态管理, 移动开发, 功能组件, 钩子API。

移动开发 0 次安装 0 次浏览 更新于 3/19/2026

名称: asyncredux-flutter-hooks 描述: 集成AsyncRedux与flutter_hooks包。涵盖添加flutter_hooks_async_redux、使用useSelector钩子,以及将钩子与AsyncRedux状态管理结合。

概述

flutter_hooks_async_redux包提供了一个基于钩子的API来访问AsyncRedux状态。如果您更喜欢使用带有钩子的功能组件,而不是基于小部件的StoreConnector模式,这个包允许您使用像useSelectoruseDispatch这样的钩子来与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: