@WrappedStore property wrapper to get rid of boilerplate

@propertyWrapper
public struct ViewStore<State, Action, LocalState>: DynamicProperty {
  public let wrappedValue: Store<State, Action>
  
  @ObservedObject public var projectedValue: ViewStore<LocalState, Action>
    
  public init(
    wrappedValue store: Store<State, Action>,
    state toLocalState: @escaping (State) -> LocalState
  ) where State: Equatable, LocalState: Equatable {
    self.init(wrappedValue: store, state: toLocalState, removeDuplicates: ==)
  }
  
  public init(
    wrappedValue store: Store<State, Action>,
    state toLocalState: @escaping (State) -> LocalState,
    removeDuplicates isDuplicate: @escaping (LocalState, LocalState) -> Bool
  ) {
    self.wrappedValue = store
    self.projectedValue = ViewStore(store.scope(state: toLocalState), removeDuplicates: isDuplicate)
  }
}

Sadly, this:

@ViewStore(state: ViewState.init) var store: Store<AppState, AppAction>

doesn't work yet:

Missing argument for parameter 'wrappedValue' in call

There is a pitch to Allow Property Wrappers with Multiple Arguments to Defer Initialization when wrappedValue is not Specified.

1 Like