Navigation: Going Back sends action twice

I'm not sure if this is related to this SwiftUI bug, but I haven't been able to fix it with the advice in that link.

For some reason, when pressing the back button (or swiping) in a navigation stack the setter in the binding gets called twice, which means the setNavigation(nil) action is sent twice.

This happens for every example in the repo. It's usually not a big deal, but if you are doing something in the reducer when the navigation goes back it could be problematic.

The way I fixed it is by taking advantage on the fact that all state is equatable and adding this override to the ViewStore method:

public func binding<LocalState> (
    get: @escaping (State) -> LocalState,
    send localStateToViewAction: @escaping (LocalState) -> Action
) -> Binding<LocalState> where LocalState: Equatable {
        get: { get(self.state) },
        set: { newLocalState, transaction in
            guard newLocalState != get(self.state) else { return }
            withAnimation(transaction.disablesAnimations ? nil : transaction.animation) {

Does this make sense or am I missing something?

I believe this is another SwiftUI bug, and I don't think it's related to the other bug you are referencing. Others have also come across this bug (outside the TCA world) and had to work around. For example, @inamiy works around it in one of his libraries by defining a removeDuplicates method on Binding. That may be a good approach for you instead of changing the binding method on ViewStore (until the bug is fixed in SwiftUI).


Yep! That works too. Thanks.

Is this fix recommended?

I believe this SwiftUI bug still exists, so the Binding.removeDuplicates() extension is still a good option.