From bc519a6ef3e9f98ff46c0304f3cb7ad681fa5955 Mon Sep 17 00:00:00 2001 From: Charles Maria Tor Date: Fri, 2 Jul 2021 14:20:03 +1000 Subject: [PATCH] Add redispatch function to reducer --- Sources/RecombinePackage/Reducer.swift | 36 +++++++++---------- .../RecombinePackage/Store/BaseStore.swift | 6 ++-- Tests/RecombineTests/ReducerTests.swift | 10 +++--- Tests/RecombineTests/TestFakes.swift | 6 ++-- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/Sources/RecombinePackage/Reducer.swift b/Sources/RecombinePackage/Reducer.swift index a610eb8..9c8f8f9 100644 --- a/Sources/RecombinePackage/Reducer.swift +++ b/Sources/RecombinePackage/Reducer.swift @@ -6,7 +6,7 @@ public protocol Reducer { var transform: Transform { get } init() init(_ transform: Transform) - func reduce(state: State, action: Action) -> State + func reduce(state: State, action: Action, redispatch: (Action...) -> Void) -> State func concat(_ other: R) -> Self where R.Transform == Transform } @@ -23,58 +23,58 @@ public extension Reducer { } public struct PureReducer: Reducer { - public typealias Transform = (_ state: State, _ action: Action) -> State + public typealias Transform = (_ state: State, _ action: Action, _ redispatch: (Action...) -> Void) -> State public let transform: Transform public init() { - transform = { state, _ in state } + transform = { state, _, _ in state } } public init(_ transform: @escaping Transform) { self.transform = transform } - public func callAsFunction(state: State, action: Action) -> State { - transform(state, action) + public func callAsFunction(state: State, action: Action, redispatch: (Action...) -> Void) -> State { + transform(state, action, redispatch) } public func concat(_ other: R) -> Self where R.Transform == Transform { - Self.init { state, action in - other.transform(self.transform(state, action), action) + Self.init { state, action, redispatch in + other.transform(self.transform(state, action, redispatch), action, redispatch) } } - public func reduce(state: State, action: Action) -> State { - transform(state, action) + public func reduce(state: State, action: Action, redispatch: (Action...) -> Void) -> State { + transform(state, action, redispatch) } } public struct MutatingReducer: Reducer { - public typealias Transform = (_ state: inout State, _ action: Action) -> Void + public typealias Transform = (_ state: inout State, _ action: Action, _ redispatch: (Action...) -> Void) -> Void public let transform: Transform public init() { - transform = { _, _ in } + transform = { _, _, _ in } } public init(_ transform: @escaping Transform) { self.transform = transform } - public func callAsFunction(state: inout State, action: Action) { - transform(&state, action) + public func callAsFunction(state: inout State, action: Action, redispatch: (Action...) -> Void) { + transform(&state, action, redispatch) } public func concat(_ other: R) -> Self where R.Transform == Transform { - Self.init { state, action in - self.transform(&state, action) - other.transform(&state, action) + Self.init { state, action, redispatch in + self.transform(&state, action, redispatch) + other.transform(&state, action, redispatch) } } - public func reduce(state: State, action: Action) -> State { + public func reduce(state: State, action: Action, redispatch: (Action...) -> Void) -> State { var s = state - transform(&s, action) + transform(&s, action, redispatch) return s } } diff --git a/Sources/RecombinePackage/Store/BaseStore.swift b/Sources/RecombinePackage/Store/BaseStore.swift index 96afee5..054eb87 100644 --- a/Sources/RecombinePackage/Store/BaseStore.swift +++ b/Sources/RecombinePackage/Store/BaseStore.swift @@ -77,8 +77,10 @@ public class BaseStore: StoreProtoco .store(in: &cancellables) postMiddlewareRefinedActions - .scan(state) { state, actions in - actions.reduce(state, reducer.reduce) + .scan(state) { [weak self] state, actions in + actions.reduce(state) { + reducer.reduce(state: $0, action: $1, redispatch: { self?.dispatch(refined: $0) }) + } } .receive(on: scheduler) .sink { [weak self] state in diff --git a/Tests/RecombineTests/ReducerTests.swift b/Tests/RecombineTests/ReducerTests.swift index 35a53b0..4748d6c 100644 --- a/Tests/RecombineTests/ReducerTests.swift +++ b/Tests/RecombineTests/ReducerTests.swift @@ -6,17 +6,17 @@ class MockReducerContainer { var reducer: MutatingReducer! init() { - reducer = .init { _, action in + reducer = .init { _, action, _ in self.calledWithAction.append(action) } } } -let increaseByOneReducer: MutatingReducer = .init { state, _ in +let increaseByOneReducer: MutatingReducer = .init { state, _, _ in state.count += 1 } -let increaseByTwoReducer: MutatingReducer = .init { state, _ in +let increaseByTwoReducer: MutatingReducer = .init { state, _, _ in state.count += 2 } @@ -30,7 +30,7 @@ class ReducerTests: XCTestCase { let combinedReducer = MutatingReducer(mockReducer1.reducer, mockReducer2.reducer) var state = TestFakes.CounterTest.State() - _ = combinedReducer.transform(&state, .noop) + _ = combinedReducer.transform(&state, .noop) { (_: TestFakes.SetAction...) in } XCTAssertEqual(mockReducer1.calledWithAction.count, 1) XCTAssertEqual(mockReducer2.calledWithAction.count, 1) @@ -44,7 +44,7 @@ class ReducerTests: XCTestCase { func testCombinesReducerResults() { let combinedReducer = MutatingReducer(increaseByOneReducer, increaseByTwoReducer) var state = TestFakes.CounterTest.State() - combinedReducer.transform(&state, .noop) + combinedReducer.transform(&state, .noop) { (_: TestFakes.SetAction...) in } XCTAssertEqual(state.count, 3) } diff --git a/Tests/RecombineTests/TestFakes.swift b/Tests/RecombineTests/TestFakes.swift index 55f2290..44b555b 100644 --- a/Tests/RecombineTests/TestFakes.swift +++ b/Tests/RecombineTests/TestFakes.swift @@ -39,7 +39,7 @@ extension TestFakes { var subState: SubState = .init() } - static let reducer: MutatingReducer = .init { state, action in + static let reducer: MutatingReducer = .init { state, action, _ in switch action { case let .sub(.set(value)): state.subState.value = value @@ -61,7 +61,7 @@ extension TestFakes { var value: String? } - static let reducer = MutatingReducer { state, action in + static let reducer = MutatingReducer { state, action, _ in switch action { case let .string(value): state.value = value @@ -78,7 +78,7 @@ extension TestFakes { var value: Int? } - static let reducer = MutatingReducer { state, action in + static let reducer = MutatingReducer { state, action, _ in switch action { case let .int(value): state.value = value