SwiftUI与Composable Architecture(TCA):如何集成子Reducer?
TCA父Reducer与子Reducer集成解决方案
你的核心问题是没有正确利用TCA的Reducer组合机制,不需要手动在Reduce闭包里更新子state,而是通过Scope将子Reducer嵌入父Reducer中,同时在View层通过scope方法传递对应子模块的Store。
1. 修正AppReducer的Reducer组合
修改AppReducer的body,使用Scope将子Reducer与父Reducer关联,自动处理state映射和action转发:
import ComposableArchitecture @Reducer struct AppReducer { struct State: Equatable { var parentState = ParentReducer.State() var childState = ChildReducer.State() } enum Action { case parent(ParentReducer.Action) case child(ChildReducer.Action) } var body: some Reducer<State, Action> { // 将父Reducer的state和action映射到AppReducer对应的字段 Scope(state: \.parentState, action: /Action.parent) { ParentReducer() } // 将子Reducer的state和action映射到AppReducer对应的字段 Scope(state: \.childState, action: /Action.child) { ChildReducer() } } }
2. 优化View层的Store传递
原View直接传递整个App的Store,不符合TCA的模块化设计,需要通过scope方法生成对应子模块的Store:
修改ParentView
struct ParentView: View { let store: StoreOf<AppReducer> var body: some View { // 生成父模块专属的Store let parentStore = store.scope(state: \.parentState, action: AppReducer.Action.parent) WithViewStore(parentStore, observe: { $0 }) { viewStore in VStack(spacing: 16.0) { Text("\(viewStore.count)") Button { viewStore.send(.increment) } label: { Text("INCREMENT") .font(.largeTitle) } // 生成子模块专属的Store传递给ChildView ChildView(store: store.scope(state: \.childState, action: AppReducer.Action.child)) } } } }
修改ChildView
让ChildView只接收子模块的Store,降低耦合:
struct ChildView: View { let store: StoreOf<ChildReducer> var body: some View { WithViewStore(store, observe: { $0 }) { viewStore in VStack(spacing: 16.0) { Text("\(viewStore.count)") Button { viewStore.send(.increment) } label: { Text("INCREMENT") .font(.largeTitle) } } } } }
关键原理说明
Scope(Reducer层):负责将父Reducer的state切片和action分支映射到子Reducer,TCA会自动调用子Reducer处理对应的action并更新state,无需手动赋值。store.scope(View层):从全局Store中生成子模块的专属Store,让View只关注自身需要的state和action,遵循单一职责原则,同时避免不必要的状态监听。
内容的提问来源于stack exchange,提问作者JamesDerrick248
相关产品推荐
相关产品推荐

