ifLet(_:action:destination:fileID:filePath:line:column:)

Embeds a child reducer in a parent domain that works on an optional property of parent state.

PresentationReducer.swift:410
@warn_unqualified_access func ifLet<DestinationState, DestinationAction, Destination>(_ toPresentationState: WritableKeyPath<State, PresentationState<DestinationState>>, action toPresentationAction: CaseKeyPath<Action, PresentationAction<DestinationAction>>, @ReducerBuilder<DestinationState, DestinationAction> destination: () -> Destination, fileID: StaticString = #fileID, filePath: StaticString = #filePath, line: UInt = #line, column: UInt = #column) -> some Reducer<State, Action> where DestinationState == Destination.State, DestinationAction == Destination.Action, Destination : Reducer

Parameters

toPresentationState

A writable key path from parent state to a property containing child presentation state.

toPresentationAction

A case path from parent action to a case containing child actions.

destination

A reducer that will be invoked with child actions against presented child state.

fileID

The fileID.

filePath

The filePath.

line

The line.

column

The column.

Returns

A reducer that combines the child reducer with the parent reducer.

This version of ifLet requires the usage of the Presents macro and PresentationAction type in your feature’s domain.

For example, if a parent feature holds onto a piece of optional child state, then it can perform its core logic and the child’s logic by using the ifLet operator:

@Reducer
struct Parent {
  @ObservableState
  struct State {
    @Presents var child: Child.State?
    // ...
  }
  enum Action {
    case child(PresentationAction<Child.Action>)
    // ...
  }

  var body: some ReducerOf<Self> {
    Reduce { state, action in
      // Core logic for parent feature
    }
    .ifLet(\.$child, action: \.child) {
      Child()
    }
  }
}

The ifLet operator does a number of things to make integrating parent and child features ergonomic and enforce correctness:

  • It forces a specific order of operations for the child and parent features:

    • When a dismiss action is sent, it runs the parent feature before the child state is nil’d out. This gives the parent feature an opportunity to inspect the child state one last time before the state is cleared.

    • When a presented(_:) action is sent it runs the child first, and then the parent. If the order was reversed, then it would be possible for the parent feature to nil out the child state, in which case the child feature would not be able to react to that action. That can cause subtle bugs.

  • It automatically cancels all child effects when it detects the child’s state is nil’d out.

  • Automatically nils out child state when an action is sent for alerts and confirmation dialogs.

  • It gives the child feature access to the DismissEffect dependency, which allows the child feature to dismiss itself without communicating with the parent.