Skip to content

Commit 6e0411b

Browse files
committed
Change Reducer to a function type
1 parent 05c0a4a commit 6e0411b

File tree

7 files changed

+24
-53
lines changed

7 files changed

+24
-53
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#Upcoming Release
2+
**Breaking API Changes:**
3+
4+
- Change Reducer to a generic function type - @Qata
5+
26
**API Changes:**
37

48
- Rename `Middleware.increase(_:)` to `Middleware.flatMap(_:)` - @Qata

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ enum AppAction: Action {
5656
Your reducer needs to respond to these different actions, that can be done by switching over the value of action:
5757

5858
```swift
59-
let appReducer = Reducer<AppState> { action, state in
59+
let appReducer: Reducer<AppState> = { action, state in
6060
switch action as? AppAction {
6161
case .Increase?:
6262
state.counter += 1
@@ -69,7 +69,7 @@ let appReducer = Reducer<AppState> { action, state in
6969
}
7070
```
7171

72-
A single `Reducer` should only deal with a single field of the state struct. You can chain together multiple reducers using `Reducer(firstReducer, secondReducer, ...)`.
72+
A single `Reducer` should only deal with a single field of the state struct. You can nest multiple reducers within your main reducer to provide separation of concerns.
7373

7474
In order to have a predictable app state, it is important that the reducer is always free of side effects, it receives the current app state and an action and returns the new app state.
7575

Sources/CoreTypes/Reducer.swift

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,4 @@
88

99
import Foundation
1010

11-
/**
12-
Reducer is a structure that allows you to modify the current state
13-
by reducing actions.
14-
*/
15-
public struct Reducer<State: StateType> {
16-
public let transform: (Action, State) -> State
17-
18-
/**
19-
Initialises the `Reducer` with a transformative function.
20-
21-
- parameter transform: The function that will be able to modify passed state.
22-
*/
23-
public init(_ transform: @escaping (Action, State) -> State) {
24-
self.transform = transform
25-
}
26-
27-
/**
28-
Initialises the `Reducer` by concatenating the transformative functions from
29-
the `Reducer`s that were passed in.
30-
*/
31-
public init(_ first: Reducer<State>, _ rest: Reducer<State>...) {
32-
self = rest.reduce(first) {
33-
$0.concat($1)
34-
}
35-
}
36-
37-
/// Concatenates the transform function of the passed `Reducer` onto the callee's transform.
38-
public func concat(_ other: Reducer<State>) -> Reducer<State> {
39-
return map(other.transform)
40-
}
41-
42-
/// Concatenates the transform function onto the callee's transform.
43-
public func map(_ transform: @escaping (Action, State) -> State) -> Reducer<State> {
44-
return Reducer<State> {
45-
return transform($0, self.transform($0, $1))
46-
}
47-
}
48-
}
11+
public typealias Reducer<State> = (_ action: Action, _ state: State) -> State

Sources/CoreTypes/Store.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ open class Store<ObservableProperty: ObservablePropertyType> where ObservablePro
1818
private let reducer: StoreReducer
1919
private let disposeBag = SubscriptionReferenceBag()
2020

21-
public required init(reducer: StoreReducer, observable: ObservableProperty, middleware: StoreMiddleware = Middleware()) {
21+
public required init(reducer: @escaping StoreReducer, observable: ObservableProperty, middleware: StoreMiddleware = Middleware()) {
2222
self.reducer = reducer
2323
self.observable = observable
2424
self.middleware = middleware
@@ -30,7 +30,7 @@ open class Store<ObservableProperty: ObservablePropertyType> where ObservablePro
3030
actions.forEach { self?.dispatch($0) }
3131
}
3232
middleware.transform({ self.observable.value }, dispatchFunction, action).forEach { action in
33-
observable.value = reducer.transform(action, observable.value)
33+
observable.value = reducer(action, observable.value)
3434
}
3535
}
3636
}

Tests/Observable/StoreTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class DeInitStore<State: StateType>: Store<ObservableProperty<State>> {
3636
deInitAction?()
3737
}
3838

39-
convenience init(reducer: Reducer<ObservableProperty<State>.ValueType>,
39+
convenience init(reducer: @escaping Reducer<ObservableProperty<State>.ValueType>,
4040
observable: ObservableProperty<State>,
4141
middleware: Middleware<ObservableProperty<State>.ValueType> = Middleware(),
4242
deInitAction: @escaping () -> Void) {
@@ -46,7 +46,7 @@ class DeInitStore<State: StateType>: Store<ObservableProperty<State>> {
4646
self.deInitAction = deInitAction
4747
}
4848

49-
required init(reducer: Reducer<ObservableProperty<State>.ValueType>,
49+
required init(reducer: @escaping Reducer<ObservableProperty<State>.ValueType>,
5050
observable: ObservableProperty<State>,
5151
middleware: Middleware<ObservableProperty<State>.ValueType>) {
5252
super.init(reducer: reducer,

Tests/ReducerTests.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ class MockReducerContainer {
1515
var reducer: Reducer<CounterState>!
1616

1717
init() {
18-
reducer = Reducer { action, state in
18+
reducer = { action, state in
1919
self.calledWithAction.append(action)
2020
return state
2121
}
2222
}
2323
}
2424

25-
let increaseByOneReducer = Reducer { action, state in
25+
let increaseByOneReducer: Reducer<CounterState> = { action, state in
2626
CounterState(count: state.count + 1)
2727
}
2828

29-
let increaseByTwoReducer = Reducer { action, state in
29+
let increaseByTwoReducer: Reducer<CounterState> = { action, state in
3030
CounterState(count: state.count + 2)
3131
}
3232

@@ -39,9 +39,11 @@ class ReducerTests: XCTestCase {
3939
let mockReducer1 = MockReducerContainer()
4040
let mockReducer2 = MockReducerContainer()
4141

42-
let combinedReducer = Reducer(mockReducer1.reducer, mockReducer2.reducer)
42+
let combinedReducer: Reducer<CounterState> = { action, state in
43+
mockReducer2.reducer(action, mockReducer1.reducer(action, state))
44+
}
4345

44-
_ = combinedReducer.transform(NoOpAction(), CounterState())
46+
_ = combinedReducer(NoOpAction(), CounterState())
4547

4648
XCTAssertEqual(mockReducer1.calledWithAction.count, 1)
4749
XCTAssertEqual(mockReducer2.calledWithAction.count, 1)
@@ -53,9 +55,11 @@ class ReducerTests: XCTestCase {
5355
it combines the results from each individual reducer correctly
5456
*/
5557
func testCombinesReducerResults() {
56-
let combinedReducer = Reducer(increaseByOneReducer, increaseByTwoReducer)
58+
let combinedReducer: Reducer<CounterState> = { action, state in
59+
increaseByTwoReducer(action, increaseByOneReducer(action, state))
60+
}
5761

58-
let newState = combinedReducer.transform(NoOpAction(), CounterState())
62+
let newState = combinedReducer(NoOpAction(), CounterState())
5963

6064
XCTAssertEqual(newState.count, 3)
6165
}

Tests/TestFakes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct SetValueStringAction: StandardActionConvertible {
6767

6868
}
6969

70-
let testReducer = Reducer<TestAppState> { action, state in
70+
let testReducer: Reducer<TestAppState> = { action, state in
7171
switch action {
7272
case let action as SetValueAction:
7373
return TestAppState(testValue: action.value)
@@ -76,7 +76,7 @@ let testReducer = Reducer<TestAppState> { action, state in
7676
}
7777
}
7878

79-
let testValueStringReducer = Reducer<TestStringAppState> { action, state in
79+
let testValueStringReducer: Reducer<TestStringAppState> = { action, state in
8080
switch action {
8181
case let action as SetValueStringAction:
8282
return TestStringAppState(testValue: action.value)

0 commit comments

Comments
 (0)