Issue with child actions not being executed when scoping with if let store = store.scope
#3556
-
Hi lads. I am having an issue where I am using an Reducerimport ComposableArchitecture
@Reducer
struct AppReducer {
enum Action {
case onAppear
case home(HomeState.Action)
case login(LoginState.Action)
}
@ObservableState
enum State {
case login(LoginState.State)
case home(HomeState.State)
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .onAppear:
state = .home(.init(data: ["Hello", "World"]))
return .none
case .home: return .none
case .login: return .none
}
}
}
}
@Reducer
struct LoginState {
enum Action {
}
@ObservableState
struct State {
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action { }
}
}
}
@Reducer
struct HomeState {
enum Action {
case something
}
@ObservableState
struct State {
var data: [String]
init(data: [String]) {
self.data = data
}
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .something:
state.data.append("Something")
return .none
}
}
}
} Viewimport SwiftUI
import ComposableArchitecture
struct AppView: View {
private var store = StoreOf<AppReducer>(initialState: .login(.init())) {
AppReducer()
}
var body: some View {
Group {
switch store.state {
case .login:
Text("Loading")
case .home:
if let store = store.scope(
state: \.home,
action: \.home
) { ContentView(store: store) }
}
}
.onAppear {
store.send(.onAppear)
}
}
}
struct ContentView: View {
var store: StoreOf<HomeState>
var body: some View {
VStack {
Text(store.data.joined(separator: " "))
Button("Something") {
store.send(.something)
}
}
.padding()
}
} Screen.Recording.2025-01-15.at.17.23.24.movMy guess is that the Screen.Recording.2025-01-15.at.17.20.23.movimport SwiftUI
import ComposableArchitecture
struct AppView: View {
@State private var store = StoreOf<AppReducer>(initialState: .login(.init())) {
AppReducer()
}
var body: some View {
Group {
switch store.state {
case .login:
Text("Loading")
case .home:
if let store = store.scope(
state: \.home,
action: \.home
) { ContentView() }
}
}
.onAppear {
store.send(.onAppear)
}
}
}
struct ContentView: View {
var store = StoreOf<HomeState>(initialState: .init(data: [""])) {
HomeState()
}
var body: some View {
VStack {
Text(store.data.joined(separator: " "))
Button("Something") {
store.send(.something)
}
}
.padding()
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @tommy-holmes, the problem is in your var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .onAppear:
state = .home(.init(data: ["Hello", "World"]))
return .none
case .home: return .none
case .login: return .none
}
}
} While you have integrated the domains of home and login into the app feature, you have not integrated their reducers. You can do so like this: var body: some ReducerOf<Self> {
Scope(state: \.home, action: \.home) {
Home()
}
Scope(state: \.login, action: \.login) {
Login()
}
Reduce { state, action in
switch action {
case .onAppear:
state = .home(.init(data: ["Hello", "World"]))
return .none
case .home: return .none
case .login: return .none
}
}
} That runs the logic of |
Beta Was this translation helpful? Give feedback.
Hi @tommy-holmes, the problem is in your
AppReducer
:While you have integrated the domains of home and login into the app feature, you have not integrated their reducers. You can do so like this: