https://github.com/manolofdez/reducedispatcher
TCA macro for routing Actions to function calls.
https://github.com/manolofdez/reducedispatcher
composable-architecture ios macros swift tca
Last synced: 8 months ago
JSON representation
TCA macro for routing Actions to function calls.
- Host: GitHub
- URL: https://github.com/manolofdez/reducedispatcher
- Owner: manolofdez
- License: mit
- Created: 2024-06-09T21:48:04.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-12T03:29:27.000Z (almost 2 years ago)
- Last Synced: 2024-06-13T04:31:40.355Z (almost 2 years ago)
- Topics: composable-architecture, ios, macros, swift, tca
- Language: Swift
- Homepage:
- Size: 42 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ReduceDispatcher
A [Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture) companion
macro that generates the boilerplate necessary for routing a Reducer's Actions to function calls.
## Motivation
TCA is awesome! State management, testability, what's not to like!? That said, I often find
myself a bit lost with all the enum cases, specifically in the Reducer's body. And while we can
always split reducers up, sometimes there isn't a clean way of divvying up its responsibilities
in a way that alleviates the problem.
What's causing this sense of disorientation? Is it the extra indentation? Is it the way each case
is separated from one another? (Is it just me?) I don't know. To get to the bottom of this, we need
to play around with some ideas!
The `ReduceDispatcher` project explores one such idea: what if we could _hide_ the Reduce's switch
statement while retaining all the pieces and concepts of TCA? Would it _feel_ better if we replaced
all enum cases in a Reducer's body with function calls?
Well, let's find out!
## Usage
Setting up the dispatcher is simple, though not entirely automatic. Take the following reducer:
```swift
@Reducer
struct MyReducer {
struct State {}
enum Action {
case didAppear
}
var body: some ReducerOf {
Reduce { _, action in
switch action {
case .didAppear:
print("foo")
}
return .none
}
}
}
```
All you need to do is:
1. Import the `ReduceDispatcher` package
2. Add the `ReduceDispatcher` annotation
3. Replace `Reduce { ...` with `Dispatch(self)`
4. Conform your reducer to the autogenerated reducer
- The name is the name of your reducer, suffixed with `ActionDelegate`
- Don't worry if this doesn't make sense. If you follow the previous
step, the compiler will yell and tell you what to do.
```swift
import ReduceDispatcher
@Reducer
@ReduceDispatcher
struct MyReducer {
struct State {}
enum Action {
case didAppear
}
var body: some ReducerOf {
Dispatch(self)
}
}
extension MyReducer: MyReducerActionDelegate {
func didAppear(state: inout State) -> Effect {
print("foo")
return .none
}
}
```
That's it!
### Dispatch skipping
Sometimes you're scoping a bunch of child reducers, or are treating some actions as events. Having to
write out a function for those just to return `.none` feels so bad, right? We gotchu! Just use the
`@SkipDispatch` macro. Like so:
```swift
import ReduceDispatcher
@Reducer
@ReduceDispatcher
struct MyReducer {
struct State {}
enum Action {
case didAppear
@SkipDispatch
case didDisappear
}
var body: some ReducerOf {
Dispatch(self)
}
}
```
## Installation
### Swift Package Manager
This library can be installed using the Swift Package Manager by adding it to your Package Dependencies.
## Requirements
- iOS 16.0+
- MacOS 13.0+
- Swift 5
- Xcoce 15.4+
## License
Licensed under MIT license.