onRecieve is printing multiple times for each view update #734
-
Hey! I'm building my first app with CA and it worked really well, until I saw the problem with view recalculating multiple for each state update. I understood the problem with scoped stores and optimizing for it, but I still don't understand is it possible to subscribe to onRecieve of only 1 property of viewStore or what it is the best way to react to store updates in the view?
that is the minimal example with the problem. ideally I want to have 2 separate onRecieve when firstTimer value updates and another one for secondTimer value updates and here goes the video where you can see print being executed twice. Thank you so much in advance 🙇♂️ |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hey Dmitry :) Here is an example to highlight how state changes are going to impact your view. struct TestView: View {
var body: some View {
VStack {
WithViewStore(store.scope(state: \.firstTimer)) {
Text("firstTimer \($0.state)")
}
WithViewStore(store.scope(state: \.secondTimer)) {
Text("secondTimer \($0.state)")
}
WithViewStore(store.stateless) { actions in
Button("IncrementFirstOne") {
actions.send(.updateFirstTimer)
}
Button("IncrementSecondOne") {
actions.send(.updateSecondTimer)
}
}
.onReceive(
ViewStore(store).publisher.firstTimer
perform: { print("first timer value \($0)") }
)
.onReceive(
ViewStore(store).publisher.secondTimer,
perform: { print("second timer value \($0)") }
)
}
}
} See how the VStack doesn't contain any state which will cause it to be redrawn. This means the onReceive modifiers are only called once. This is also true for the Buttons because the the In terms of reacting to state changes, normally I would do this in the reducer. I think using the ViewStore(store).publisher would work fine for you though. Let me know if this makes sense. |
Beta Was this translation helpful? Give feedback.
Hey Dmitry :)
Part of the problem is that onReceive is inside WithViewStore. This means it will be recreated whenever state changes, which will occur when either of the timer values change. Keep in mind onReceive is going to emit the initial value as the view appears as well.
Here is an example to highlight how state changes are going to impact your view.