> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pointfreeco/swift-composable-architecture/llms.txt
> Use this file to discover all available pages before exploring further.

# State Management

> How TCA manages state using value types and observation

# State Management

The Composable Architecture uses value types (structs and enums) to model application state in a predictable and testable way. State is immutable from the outside and can only be modified by reducers in response to actions.

## Value Types for State

TCA encourages using Swift structs and enums to define your feature's state:

```swift State.swift theme={null}
@ObservableState
struct State {
  var count: Int = 0
  var isLoading: Bool = false
  var error: String?
}
```

### Benefits of Value Types

<CardGroup cols={2}>
  <Card title="Predictability" icon="check-circle">
    State changes are explicit and traceable through actions
  </Card>

  <Card title="Testability" icon="vial">
    Easy to construct any state for testing scenarios
  </Card>

  <Card title="Thread Safety" icon="lock">
    Value semantics eliminate shared mutable state issues
  </Card>

  <Card title="Time Travel" icon="clock-rotate-left">
    Snapshots enable undo/redo and debugging features
  </Card>
</CardGroup>

## Observable State

The `@ObservableState` macro enables SwiftUI views to observe state changes efficiently:

```swift Feature.swift theme={null}
@Reducer
struct Feature {
  @ObservableState
  struct State {
    var username: String = ""
    var isLoggedIn: Bool = false
  }
  
  enum Action {
    case usernameChanged(String)
    case loginButtonTapped
  }
  
  var body: some Reducer<State, Action> {
    Reduce { state, action in
      switch action {
      case let .usernameChanged(username):
        state.username = username
        return .none
        
      case .loginButtonTapped:
        state.isLoggedIn = true
        return .none
      }
    }
  }
}
```

<Note>
  The `@ObservableState` macro conforms your state to the `ObservableState` protocol, which enables observation through Swift's Observation framework (iOS 17+) or the Perception package (iOS 13-16).
</Note>

### How Observable State Works

The macro adds the following to your state type:

* `_$id: ObservableStateID` - A unique identifier that changes when state mutates
* `_$willModify()` - Called before any property modification
* Observation registrar for tracking access and mutations

```swift theme={null}
// Simplified macro expansion
@ObservableState
struct State {
  var count: Int = 0
  
  // Generated by macro:
  var _$id = ObservableStateID()
  var _$observationRegistrar = ObservationRegistrar()
  
  mutating func _$willModify() {
    _$id._$willModify()
  }
}
```

## State Composition

Compose larger state from smaller pieces:

```swift AppState.swift theme={null}
@ObservableState
struct AppState {
  var profile: Profile.State
  var settings: Settings.State
  var search: Search.State
}
```

### Optional State

Use optionals to represent state that may not exist:

```swift theme={null}
@ObservableState
struct State {
  var user: User?
  @Presents var alert: AlertState<Action.Alert>?
}
```

<Tip>
  Use the `@Presents` macro instead of manually wrapping state in `PresentationState` when using `@ObservableState`.
</Tip>

### Collection State

Manage collections of child features:

```swift theme={null}
import IdentifiedCollections

@ObservableState
struct State {
  var todos: IdentifiedArrayOf<Todo.State> = []
}

struct Todo: Reducer {
  @ObservableState
  struct State: Identifiable {
    let id: UUID
    var description: String
    var isComplete: Bool
  }
  // ...
}
```

## State Mutations

<Warning>
  State should **only** be mutated inside reducers. Direct mutation from views or effects will not trigger observations and can lead to inconsistent state.
</Warning>

### Correct: Mutate in Reducer

```swift theme={null}
var body: some Reducer<State, Action> {
  Reduce { state, action in
    switch action {
    case .incrementButtonTapped:
      state.count += 1  // ✅ Correct
      return .none
    }
  }
}
```

### Incorrect: Direct Mutation

```swift theme={null}
struct MyView: View {
  let store: StoreOf<Feature>
  
  var body: some View {
    Button("Increment") {
      store.state.count += 1  // ❌ Won't compile - state is read-only
    }
  }
}
```

## Accessing State

Access state from the store in different contexts:

### In SwiftUI Views

```swift theme={null}
struct FeatureView: View {
  let store: StoreOf<Feature>
  
  var body: some View {
    // Direct property access
    Text("Count: \(store.count)")
  }
}
```

### Using withState

For non-observable contexts or when you need a snapshot:

```swift theme={null}
store.withState { state in
  print("Current count: \(state.count)")
  return state.count * 2
}
```

## Enum State

Model exclusive states using enums:

```swift theme={null}
@ObservableState
enum LoadingState<Data> {
  case idle
  case loading
  case loaded(Data)
  case failed(Error)
}

@ObservableState
struct State {
  var data: LoadingState<[Item]> = .idle
}
```

## Best Practices

<Steps>
  <Step title="Keep State Minimal">
    Only store the minimum necessary state. Derive computed values in views or using computed properties.

    ```swift theme={null}
    @ObservableState
    struct State {
      var firstName: String = ""
      var lastName: String = ""
      
      // Computed property - not stored
      var fullName: String {
        "\(firstName) \(lastName)"
      }
    }
    ```
  </Step>

  <Step title="Use Value Types">
    Prefer structs and enums over classes for state. This ensures copy-on-write semantics and value equality.
  </Step>

  <Step title="Make State Codable">
    When appropriate, conform state to `Codable` for persistence:

    ```swift theme={null}
    @ObservableState
    struct State: Codable {
      var settings: UserSettings
      var lastSyncDate: Date?
    }
    ```
  </Step>

  <Step title="Normalize Collections">
    Use `IdentifiedArray` instead of `Array` for collections of identifiable items:

    ```swift theme={null}
    // ❌ Avoid
    var users: [User] = []

    // ✅ Prefer
    var users: IdentifiedArrayOf<User> = []
    ```
  </Step>
</Steps>

## Related Topics

* [Reducers](/concepts/reducers) - Learn how state is modified
* [Store](/concepts/store) - Understand the runtime container for state
* [Composition](/concepts/composition) - Compose state from smaller pieces
