name: asyncredux-base-action description: 为您的应用程序创建自定义基础动作类。涵盖添加状态部分的getter快捷方式、添加选择器方法、实现共享错误处理逻辑以及建立项目范围内的动作约定。
创建自定义基础动作类
每个AsyncRedux应用程序都应定义一个抽象基础动作类,所有动作都扩展这个类。这为以下提供了中心位置:
- 方便的getter快捷方式访问状态部分
- 选择器方法用于常见查询
- 共享错误处理逻辑
- 类型安全的环境访问
- 项目范围内的约定
基础基础动作设置
创建一个抽象类扩展 ReduxAction<AppState>。推荐的名称为 AppAction,在文件 app_action.dart 中:
abstract class AppAction extends ReduxAction<AppState> {
// 所有您的动作都将扩展这个类
}
然后在所有动作中扩展 AppAction 而不是 ReduxAction<AppState>:
class IncrementCounter extends AppAction {
@override
AppState reduce() => state.copy(counter: state.counter + 1);
}
添加状态部分的Getter快捷方式
当您的状态有嵌套对象时,添加getter以简化访问:
abstract class AppAction extends ReduxAction<AppState> {
// 对嵌套状态部分的快捷方式
User get user => state.user;
Settings get settings => state.settings;
IList<Todo> get todos => state.todos;
Cart get cart => state.cart;
}
现在动作可以编写更简洁的代码:
class UpdateUserName extends AppAction {
final String name;
UpdateUserName(this.name);
@override
AppState reduce() {
// 而不是:state.user.name
// 您可以写:user.name
return state.copy(user: user.copy(name: name));
}
}
添加选择器方法
对于常见数据查找,直接将选择器方法添加到您的基础动作中:
abstract class AppAction extends ReduxAction<AppState> {
// 状态部分的getter
User get user => state.user;
IList<Item> get items => state.items;
// 选择器方法
Item? findItemById(String id) =>
items.firstWhereOrNull((item) => item.id == id);
List<Item> get completedItems =>
items.where((item) => item.isCompleted).toList();
bool get isLoggedIn => user.isAuthenticated;
}
动作然后可以使用这些选择器:
class MarkItemComplete extends AppAction {
final String itemId;
MarkItemComplete(this.itemId);
@override
AppState reduce() {
final item = findItemById(itemId);
if (item == null) return null; // 无变化
return state.copy(
items: items.replaceFirstWhere(
(i) => i.id == itemId,
item.copy(isCompleted: true),
),
);
}
}
使用单独的选择器类
对于大多数应用程序,最好使用一个专门的选择器类来保持基础动作的清洁:
class ActionSelect {
final AppState state;
ActionSelect(this.state);
Item? findById(String id) =>
state.items.firstWhereOrNull((item) => item.id == id);
List<Item> get completed =>
state.items.where((item) => item.isCompleted).toList();
List<Item> get pending =>
state.items.where((item) => !item.isCompleted).toList();
}
abstract class AppAction extends ReduxAction<AppState> {
ActionSelect get select => ActionSelect(state);
}
这将选择器命名空间在 select 下,启用IDE自动补全:
class ProcessItem extends AppAction {
final String itemId;
ProcessItem(this.itemId);
@override
AppState reduce() {
// IDE自动补全显示:select.findById, select.completed, 等。
final item = select.findById(itemId);
// ...
}
}
类型安全的环境访问
对于依赖注入,在您的基础动作中覆盖 env getter:
class Environment {
final ApiClient api;
final AuthService auth;
final AnalyticsService analytics;
Environment({
required this.api,
required this.auth,
required this.analytics,
});
}
abstract class AppAction extends ReduxAction<AppState> {
// 类型安全的环境访问
@override
Environment get env => super.env as Environment;
// 常见服务的便利getter
ApiClient get api => env.api;
AuthService get auth => env.auth;
}
动作然后可以直接使用服务:
class FetchUserProfile extends AppAction {
@override
Future<AppState?> reduce() async {
// 使用基础动作中的api getter
final profile = await api.getUserProfile();
return state.copy(user: profile);
}
}
参考文献
文档中的URL:
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/advanced-actions/action-selectors
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/wrapping-the-reducer
- https://asyncredux.com/flutter/advanced-actions/action-mixins
- https://asyncredux.com/flutter/advanced-actions/aborting-the-dispatch
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/basics/state
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/business-logic
- https://asyncredux.com/flutter/miscellaneous/dependency-injection