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 {
    Binding(
        get: { get(self.state) },
        set: { newLocalState, transaction in
            guard newLocalState != get(self.state) else { return }
            withAnimation(transaction.disablesAnimations ? nil : transaction.animation) {
                self.send(localStateToViewAction(newLocalState))
            }
    })
}

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).

2 Likes

Yep! That works too. Thanks.

Terms of Service

Privacy Policy

Cookie Policy