I have a state that has a bool and an optional array.
struct ThingListState: Equatable {
var flag: Bool = true
var things: [Thing]? = nil
}
During the view's life cycle the boolean flips and optional array (that was nil) turns to an empty array.
state.flag = false
state.things = []
And after these mutations I return Effect.none
from the reducer.
The problem is that the view doesn't get re-rendered after the state change. All of the rendition logic is inside WithViewStore
.
Using the .debug()
on my main reducer I can see the following sequence of actions and state changes:
[Things]: Evaluating WithViewStore<ThingListState, ThingListAction, ...>.body
received action:
ThingListAction.loadThings
(No state changes)
[Things]: Evaluating WithViewStore<ThingListState, ThingListAction, ...>.body
received action:
ThingListAction.loadedThings(
[
]
)
ThingListState(
− things: nil,
− flag: true,
+ things: [
+ ],
+ flag: false
)
[Things]: Evaluating WithViewStore<ThingListState, ThingListAction, ...>.body
The [Things]
marker is placed as a debug()
view modifier for WithViewStore(store)
container. So I can see that the re-rendering is being requested, however the content on the screen doesn't change.
The simplified version of the ThingListView
is following:
struct ThingListView: View {
var store: Store<ThingListState, ThingListAction>
var body: some View {
WithViewStore(store) { viewStore in
if viewStore.flag {
Text("Loading...")
} else if viewStore.thingStates.isEmpty {
Text("No things.")
} else {
// do the `ForEachState` with `thingStates`
// omitted for brevity
}
}
}
}
Am I missing something trivial?