tokopedia / RxComposableArchitecture

RxComposableArchitecture is a forked of Composable Architecture with adjustment to make it work with UIKit.
Apache License 2.0
31 stars 5 forks source link

NeverEqual #18

Closed jeffersonsetiawan closed 2 years ago

jeffersonsetiawan commented 2 years ago

This PropertyWrapper is used for the UI that doesn't have an actual clear state, for example is scroll to top or run an animation, We only give the instruction about what to do, code example:

 struct EmitState: Equatable {
     var scrollToTop: Stateless?
 }

 enum EmitAction: Equatable {
     case didTapScrollToTop
     case resetScrollToTop
 }

 // reducer

 Reducer {
   switch action {
     case .didTapScrollToTop:
         state.scrollToTop = Stateless()
         return Effect(value: .resetScrollToTop)
     case .resetScrollToTop:
         state.scrollToTop = nil
         return .none
   }
 }

By default, if scrollToTop property never get resetted, it will never emit again even though you are sending multiple .didTapScrollToTop action to the reducer. This is because the store.subscribe has distinctUntilChanged, so the subscribe will only be emitted once it's not equal from the previous property.

We usually do this juggling (set and reset) because we don't know when the right time to reset the property, and when PointFree enhance its store.send mechanism, this mechanism will not work.

When using the NeverEqual, you don't need to reset the state again just to make it not equal.

 struct EmitState: Equatable {
     @NeverEqual var scrollToTop: Stateless?
 }

 Reducer {
   switch action {
     case .didTapScrollToTop:
         state.scrollToTop = Stateless()
         return .none
    }
 }

 // UI

 store.subscribeNeverEqual(\.$scrollToTop)
    .subscribe(onNext: { ... })

Behind the scene, the property wrapper will increment the number everytime you set it to new value, so it will not equal.