An open API service indexing awesome lists of open source software.

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.

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.