Skip to content

Guide · Open source

How to use swift-composable-architecture: state, reducers and effects

Updated · written with AI from the project's own documentation and checked against our catalogue data

The Composable Architecture (TCA) is a Swift library for building apps on Apple platforms in a consistent, understandable way, with composition, testing and ergonomics in mind. This guide is for Swift developers who want a clear structure for SwiftUI or UIKit features. After reading it, you will know the core pieces (state, actions, reducer and store), how a feature handles side effects, and where to find the library and its examples.

The Composable Architecturepointfreeco/swift-composable-architecture · ★ 15k · MIT

Quick start

  1. 1Check prerequisites. Make sure you have Xcode with Swift Package Manager support installed.
  2. 2Add the package. Add swift-composable-architecture to your project through Swift Package Manager, using the repository at github.com/pointfreeco/swift-composable-architecture.
  3. 3Define the state. Create a @Reducer type with a State struct marked @ObservableState holding the feature's data.
  4. 4Define the actions. Add an Action enum listing every user action, notification and response the feature handles.
  5. 5Write the reducer body. Implement body with Reduce, updating state and returning .none or an effect such as .run for async work.
  6. 6Connect a view to the store. Hold a StoreOf for your feature in a SwiftUI view, render from state and send actions to the store.

What does the Composable Architecture give you?

The library provides a few core tools for building applications of varying purpose and complexity. It covers state management, composition of smaller features, explicit side effects, testing, and an API meant to use as few concepts as possible.

It can be used in SwiftUI, UIKit and other setups on any Apple platform, including iOS, macOS, iPadOS, visionOS, tvOS and watchOS.

  • State management with simple value types, shared across screens
  • Composition of large features into smaller components that can live in their own modules
  • Side effects such as API requests kept testable and easy to follow
  • Testing of single features, composed features and end-to-end side effects

Install swift-composable-architecture with Swift Package Manager

The library is distributed as a Swift package, so you add it to your project through Swift Package Manager. You need Xcode with Swift Package Manager support. The README's install instruction is shown below; check the repository's installation section for the exact steps to add the package to your project.

  • Prerequisite: Xcode with Swift Package Manager support
  • Add the package to your Xcode project or Swift package
git clone https://github.com/pointfreeco/swift-composable-architecture

Model a feature with state, actions and a reducer

To build a feature you define the types that model your domain. State describes the data the feature needs for its logic and UI. Action lists everything that can happen in the feature, such as user taps, notifications and event sources. The reducer describes how state evolves for each action and returns any effects to run.

Mark the feature type with the @Reducer macro and annotate State with @ObservableState so the library's observation tools can be used.

  • State: a type holding the data the feature needs
  • Action: an enum of all things that can happen in the feature
  • Reducer: logic that updates state and returns effects, using Reduce and .none when no effect is needed
  • Store: the runtime that runs the reducer and effects and lets the UI observe changes
@Reducer struct Feature { @ObservableState struct State: Equatable { var count = 0 var numberFact: String? } enum Action { case decrementButtonTapped case incrementButtonTapped case numberFactButtonTapped case numberFactResponse(String) } var body: some Reducer<State, Action> { Reduce { state, action in switch action { case .decrementButtonTapped: state.count -= 1 return .none case .incrementButtonTapped: state.count += 1 return .none case .numberFactButtonTapped: return .run { [count = state.count] send in let (data, _) = try await URLSession.shared.data( from: URL(string: "http://number-trivia.com/\(count)/trivia")! ) await send( .numberFactResponse(String(decoding: data, as: UTF8.self)) ) } case let .numberFactResponse(fact): state.numberFact = fact return .none } } } }

Run side effects explicitly with Effect

Side effects such as API requests are returned from the reducer as an Effect value rather than run directly inside the view. In the example, the .run effect performs the request and sends the result back as a new action, numberFactResponse, which the reducer then handles like any other action.

Capturing values such as count in the effect's capture list lets the effect use the state as it was when the action started.

  • Return .none when an action needs no effect
  • Return .run to perform async work and send actions back to the store

Connect the feature to a SwiftUI view

The view holds a StoreOf<Feature>. It observes the store so it re-renders when state changes, and it sends user actions to the store instead of changing state itself. The README's full view example is in the repository's examples, which include a getting-started case study.

  • Keep the store as a let property of the view
  • Send user actions to the store rather than mutating state in the view

Where to learn more and find examples

The repository contains many examples, including a getting-started case study, case studies on effects, navigation and reusable components, and sample apps such as SyncUps, Todos and Voice memos. The README links a step-by-step interactive tutorial called Meet the Composable Architecture and a multipart tour on the Point-Free site.

The library was designed over many episodes of the Point-Free video series, and the homepage is https://www.pointfree.co/collections/composable-architecture.

  • Examples directory in the repository
  • Meet the Composable Architecture interactive tutorial
  • Point-Free tour of the architecture from scratch

What people use it for

  • Building a SwiftUI feature such as a counter with a button that fetches data from an API
  • Splitting a large screen into smaller features that are composed together
  • Writing unit tests for a feature's state changes and side effects
  • Following the example apps such as SyncUps, Todos or Voice memos to see common patterns

Frequently asked questions

Is swift-composable-architecture free to use?

The library is released under the MIT licence, as stated in the project's listing. Check the LICENSE file in the repository for the full terms before using it in a commercial product.

How do I install swift-composable-architecture?

It is installed with Swift Package Manager, which requires Xcode with Swift Package Manager support. The README's install instruction shows cloning the repository at github.com/pointfreeco/swift-composable-architecture; add it to your project as a package dependency.

Does swift-composable-architecture work with UIKit?

The README says the library can be used in SwiftUI, UIKit and more, on any Apple platform. Its examples focus on SwiftUI.

Do I need to know Swift well before using it?

Yes. The library assumes familiarity with the Swift language, and the README points beginners to a separate interactive tutorial, Meet the Composable Architecture.

What are the alternatives to swift-composable-architecture?

Comparable projects mentioned for this item include ReSwift, The Elm Architecture ports for Swift, and other Redux-style Swift libraries. They follow similar state-and-action ideas.

Is swift-composable-architecture hard to learn?

It has many concepts to learn, including state, actions, reducers, stores and effects. If you want a small approach with few concepts, a lighter architecture may suit you better.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

Choose the Composable Architecture if you build SwiftUI or UIKit apps and want a consistent structure, composable features and testable side effects, and you are willing to learn its concepts. If you want a lightweight approach, are new to Swift, or work outside Apple platforms, pick a simpler option or a different tool.

Install options & downloads