name: asyncredux-sync-actions description: 创建 AsyncRedux (Flutter) 同步动作,通过实现 reduce() 方法返回新状态,立即更新状态。
AsyncRedux 同步动作
基本同步动作结构
同步动作从其 reduce() 方法返回 AppState?。动作立即完成,状态立即更新。
class Increment extends ReduxAction<AppState> {
@override
AppState? reduce() => state.copy(counter: state.counter + 1);
}
关键组件
扩展 ReduxAction
每个动作扩展 ReduxAction<AppState>:
class MyAction extends ReduxAction<AppState> {
@override
AppState? reduce() {
// 返回新状态
}
}
state Getter
在 reduce() 中,通过 state getter 访问当前状态:
class ToggleFlag extends ReduxAction<AppState> {
@override
AppState? reduce() => state.copy(flag: !state.flag);
}
通过构造函数传递参数
通过构造函数字段将数据传递给动作:
class SetName extends ReduxAction<AppState> {
final String name;
SetName(this.name);
@override
AppState? reduce() => state.copy(name: name);
}
class IncrementBy extends ReduxAction<AppState> {
final int amount;
IncrementBy({required this.amount});
@override
AppState? reduce() => state.copy(counter: state.counter + amount);
}
修改嵌套状态
对于嵌套状态对象,首先创建新的嵌套对象:
class UpdateUserName extends ReduxAction<AppState> {
final String name;
UpdateUserName(this.name);
@override
AppState? reduce() {
var newUser = state.user.copy(name: name);
return state.copy(user: newUser);
}
}
分发同步动作
从 Widgets 中
使用上下文扩展:
// 触发并忘记
context.dispatch(Increment());
// 带参数
context.dispatch(SetName('Alice'));
context.dispatch(IncrementBy(amount: 5));
立即状态更新
同步动作立即更新状态:
print(store.state.counter); // 2
store.dispatch(IncrementBy(amount: 3));
print(store.state.counter); // 5
使用 dispatchSync() 保证同步
dispatchSync() 如果动作是异步的,则抛出 StoreException。否则,它的行为与 dispatch() 完全相同。
仅当您必须确保动作是同步的,因为需要在分发返回后立即应用状态时,使用 dispatchSync()。
context.dispatchSync(Increment());
从其他动作中
动作可以分发其他动作:
class ResetAndIncrement extends ReduxAction<AppState> {
@override
AppState? reduce() {
dispatch(Reset());
dispatch(Increment());
return null; // 这个动作本身不改变状态
}
}
返回 Null(无状态变化)
当不需要改变状态时,返回 null:
class LogCurrentState extends ReduxAction<AppState> {
@override
AppState? reduce() {
print('当前计数器:${state.counter}');
return null; // 无状态变化
}
}
条件状态变化:
class IncrementIfPositive extends ReduxAction<AppState> {
final int amount;
IncrementIfPositive(this.amount);
@override
AppState? reduce() {
if (amount <= 0) return null;
return state.copy(counter: state.counter + amount);
}
}
使用基类简化动作
创建一个基动作类以减少样板代码:
// 定义一次
abstract class AppAction extends ReduxAction<AppState> {}
// 到处使用
class Increment extends AppAction {
@override
AppState? reduce() => state.copy(counter: state.counter + 1);
}
class SetName extends AppAction {
final String name;
SetName(this.name);
@override
AppState? reduce() => state.copy(name: name);
}
您可以为基类添加共享功能:
abstract class AppAction extends ReduxAction<AppState> {
// 状态部分的快捷方式
User get user => state.user;
Settings get settings => state.settings;
}
class UpdateEmail extends AppAction {
final String email;
UpdateEmail(this.email);
@override
AppState? reduce() => state.copy(
user: user.copy(email: email), // 使用快捷方式
);
}
返回类型警告
reduce() 方法签名是 FutureOr<AppState?>。对于同步动作,始终直接返回 AppState?:
// 正确 - 同步动作
AppState? reduce() => state.copy(counter: state.counter + 1);
// 错误 - 不要直接返回 FutureOr
FutureOr<AppState?> reduce() => state.copy(counter: state.counter + 1);
如果您直接返回 FutureOr<AppState?>,AsyncRedux 无法确定动作是同步还是异步,将抛出 StoreException。
完整示例
// 状态
class AppState {
final int counter;
final String name;
AppState({required this.counter, required this.name});
static AppState initialState() => AppState(counter: 0, name: '');
AppState copy({int? counter, String? name}) => AppState(
counter: counter ?? this.counter,
name: name ?? this.name,
);
}
// 基动作
abstract class AppAction extends ReduxAction<AppState> {}
// 同步动作
class Increment extends AppAction {
@override
AppState? reduce() => state.copy(counter: state.counter + 1);
}
class Decrement extends AppAction {
@override
AppState? reduce() => state.copy(counter: state.counter - 1);
}
class IncrementBy extends AppAction {
final int amount;
IncrementBy(this.amount);
@override
AppState? reduce() => state.copy(counter: state.counter + amount);
}
class SetName extends AppAction {
final String name;
SetName(this.name);
@override
AppState? reduce() => state.copy(name: name);
}
class Reset extends AppAction {
@override
AppState? reduce() => AppState.initialState();
}
// 在 widget 中使用
ElevatedButton(
onPressed: () => context.dispatch(IncrementBy(5)),
child: Text('Add 5'),
)
参考
文档中的 URL:
- https://asyncredux.com/flutter/basics/sync-actions
- https://asyncredux.com/flutter/basics/actions-and-reducers
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/action-simplification
- https://asyncredux.com/flutter/basics/changing-state-is-optional