Jan 7, 2025

Present a sheet using TCA

Here's how you can present a SwiftUI sheet using the Composable Architecture.

import ComposableArchitecture
import SwiftUI

@Reducer
struct ShowSheetFeature {
  @ObservableState
  struct State: Equatable {
    @Presents var destination: Destination.State?
  }
  
  enum Action: BindableAction {
    case binding(BindingAction<State>)
    case destination(PresentationAction<Destination.Action>)
    
    case showDetail
  }
  
  @Reducer(state: .equatable)
  enum Destination {
    case detail(DetailFeature)
  }
  
  var body: some Reducer<State, Action> {
    BindingReducer()
    Reduce { state, action in
      switch action {
      case .showDetail:
        state.destination = .detail(DetailFeature.State())
        return .none
      case .binding, .destination:
        return .none
      }
    }
    .ifLet(\.$destination, action: \.destination)
  }
}

struct ShowSheetView: View {
  @Bindable var store: StoreOf<ShowSheetFeature>
  
  var body: some View {
    VStack {
      Button("Show Detail") {
        store.send(.showDetail)
      }
    }
    .sheet(item: $store.scope(state: \.destination?.detail, action: \.destination.detail)) { store in
      DetailView(store: store)
    }
  }
}