Composition
Composition is a core principle of TCA. It allows you to build complex features from smaller, focused features that can be developed, tested, and reasoned about independently. TCA provides several tools for composing features together.Why Composition?
Modularity
Break large features into smaller, manageable pieces
Reusability
Share features across different parts of your app
Testability
Test features in isolation without dependencies
Team Collaboration
Different team members can work on separate features
Composing State
Compose larger state from smaller state types:AppFeature.swift
Child Features
Each child feature is independent:Profile.swift
Composing Reducers
Use theScope reducer to embed child reducers:
AppFeature.swift
Child reducers run before parent logic. This ensures children process their actions before the parent potentially changes the state structure.
Optional Child State
Compose features that may not always be present:The @Presents Macro
The@Presents macro simplifies working with optional child state:
Collection Composition
Compose features for collections of child state:TodoList.swift
IdentifiedArray
UseIdentifiedArray for collections:
Enum-Based Composition
Use enums to model mutually exclusive child states:Destination.swift
Parent-Child Communication
Children can communicate with parents through delegate actions:ChildFeature.swift
Parent Handling Delegate Actions
ParentFeature.swift
Delegate actions are a clean way for children to notify parents without creating tight coupling.
Combining Multiple Reducers
UseCombineReducers to group reducers:
Scoping Stores
Scope stores to pass to child views:AppView.swift
Benefits of Scoping
- Type Safety: Child views can’t access parent state
- Performance: Views only re-render when their scope changes
- Modularity: Child features can be extracted to separate modules
- Testing: Features can be tested independently
Navigation Patterns
Stack-Based Navigation
For navigation stacks:Tree-Based Navigation
For sheets, popovers, and alerts:Testing Composed Features
Test features in isolation:ChildTests.swift
ParentTests.swift
Best Practices
1
Start Small
Begin with small, focused features before composing them:
2
Compose Hierarchically
Build features in layers:
3
Use Delegate Actions
Children should communicate with parents through delegate actions, not by directly modifying parent state.
4
Scope Appropriately
Scope stores to give views only what they need:
5
Keep Features Independent
Features should work without knowledge of their parents:
Common Patterns
Shared State
Use the@Shared property wrapper for state shared across features:
Cross-Feature Communication
Use effects to communicate between siblings:Progressive Disclosure
Load child features lazily:Related Topics
- Reducers - Building blocks of composition
- State Management - Composing state
- Store - Scoping stores
- Navigation - Navigation patterns in TCA