Relux /rēˈlʌks/ n.
- Architecture pattern: Redux's Swift-y cousin who went to actor school and came back async.
- Framework: Your app's state management therapist - keeps data flowing in one direction, prevents race conditions, and plays nice with SwiftUI.
Etymology: Redux + Relax = Just let the actors handle it™
Relux is a Swift package that re-imagines the popular Redux pattern using Swift concurrency. The library embraces the unidirectional data flow (UDF) style while taking advantage of actors and structured concurrency to keep state management safe and predictable.
It can be gradually adopted in existing projects, works seamlessly with SwiftUI, and scales from simple applications to complex modular architectures.
UDF stands for Unidirectional Data Flow. All changes in the application are triggered by actions that are dispatched through a single channel. Each action updates the application module's state, and views observe that state. This one-way flow of information keeps behavior easy to reason about.
Relux follows the same principles as Redux but introduces several features tailored for Swift on Apple platforms:
- Actor-based state and sagas – every
BusinessStateandSagais an actor. This ensures updates run without data races and enables usage from async contexts. - Serial or concurrent dispatch – actions can be executed sequentially or concurrently using built-in helpers.
- Modular registration – a
Modulegroups states and sagas and can be registered or removed at runtime, enabling progressive adoption. - Effects and flows – asynchronous work is modeled as
Effectobjects handled bySagaorFlowactors, separating side effects from pure actions. - Enum reflection for logging – the optional logging interface introspects action enums to print meaningful messages for all effects and actions without manual boilerplate.
- Reducer inside state – reducers are instance methods that mutate the state's properties directly. This avoids constant state recreation and keeps logic close to the data it updates.
Relux provides three state types, each designed for specific use cases:
HybridState – Start here! Combines business logic and UI reactivity in one place. Runs on the main actor, perfect for SwiftUI views. Use this until you need more complexity.
BusinessState + UIState – When your app grows, split concerns:
BusinessState: Actor-based, holds your core data and business logic. Not directly observable by SwiftUI.UIState: Observable wrapper that subscribes to BusinessState changes and transforms data for the UI.
When to use what:
- Simple features ->
HybridState - Complex features with shared data ->
BusinessState+UIState - Need to aggregate and map data from multiple domains -> multiple
BusinessState's' +UIStateinstance to subscribe and aggregate
Think of it like cooking: HybridState is your all-in-one pressure cooker, while BusinessState + UIState is your professional kitchen with separate prep and plating stations.
Relux encourages dividing your codebase into feature modules. A Module bundles states, sagas or flows, and supporting services. Sagas orchestrate effects such as network requests, while services encapsulate integrations with APIs, databases, sensors etc. Modules can be registered at runtime and expose states ready for consumption by the UI or by other modules.
- Sample App - Full-featured example application
- API Reference - Coming soon
- Architecture Guide - Coming soon
- Swift 5.10+
- iOS 13.0+, macOS 10.15+, tvOS 13.0+, watchOS 6.0+
Relux is released under the MIT License.
