I implemented a ReduceStore that iterates over an Store<IdentifiedArrayOf<Element>, (Element.ID, ElementAction)>
and hands an accumulator view and a Store<Element, ElementAction>
to ViewBuilder closure.
I checked both IfLetStore and ForEachStore:
// IfLetStore
if var state = viewStore.state {
return ifContent(
store.scope {
state = $0 ?? state
return state
}
)
} else {
return nil
}
// ForEachStore
WithViewStore(store.scope(state: { $0.ids })) { viewStore in
ForEach(viewStore.state, id: \.self) { id -> EachContent in
// NB: We cache elements here to avoid a potential crash where SwiftUI may re-evaluate
// views for elements no longer in the collection.
//
// Feedback filed: https://gist.github.com/stephencelis/cdf85ae8dab437adc998fb0204ed9a6b
var element = store.state.value[id: id]!
return content(
store.scope(
state: {
element = $0[id: id] ?? element
return element
},
action: { (id, $0) }
)
)
}
There is a $0 ?? pattern used here that uses the cached value whenever the scoped state is nil. As the state is observed through the outer WithViewStore, I was curious if there is reason why the cached state isn't used directly replacing { $0 ?? state }
with { _ in state }
. The state value is captured by the scope closure and written to on every evaluation. Is this really necessary or should relying on SwiftUI to reevaluate the body whenever the ViewStore changes be enough?