Last active
June 21, 2021 18:17
-
-
Save manmal/be3a3ffa36de8614709e5531fc753c79 to your computer and use it in GitHub Desktop.
On-change handlers for Composable Architecture Reducers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Original version from the authors of ComposableArchitecture here: | |
// https://github.com/pointfreeco/isowords/blob/fcff52ccf176f40db55951d5897def7cd9b879cf/Sources/TcaHelpers/OnChange.swift | |
// | |
// The following adds a method for filtering changes with a predicate. | |
// This is written using reactiveswift-composable-architecture, but can be adapted very quickly for Combine. | |
import ComposableArchitecture | |
import ReactiveSwift | |
public extension Reducer { | |
func onChange<LocalState>( | |
of toLocalState: @escaping (State) -> LocalState, | |
by predicate: @escaping (_ from: LocalState, _ to: LocalState) -> Bool = { $0 != $1 }, | |
perform additionalEffects: @escaping (LocalState, inout State, Action, Environment) | |
-> Effect< | |
Action, Never | |
> | |
) -> Self where LocalState: Equatable { | |
.init { state, action, environment in | |
var previousLocalState = toLocalState(state) | |
defer { previousLocalState = localState } | |
let effects = self.run(&state, action, environment) | |
let localState = toLocalState(state) | |
var mergedEffects: SignalProducer<Action, Never> { | |
.merge( | |
effects, | |
additionalEffects(localState, &state, action, environment) | |
) | |
} | |
return predicate(previousLocalState, localState) ? | |
mergedEffects : | |
effects | |
} | |
} | |
func onChange<LocalState>( | |
of toLocalState: @escaping (State) -> LocalState, | |
perform additionalEffects: @escaping ( | |
LocalState, | |
LocalState, | |
inout State, | |
Action, | |
Environment | |
) | |
-> Effect<Action, Never> | |
) -> Self where LocalState: Equatable { | |
.init { state, action, environment in | |
var previousLocalState = toLocalState(state) | |
defer { previousLocalState = localState } | |
let effects = self.run(&state, action, environment) | |
let localState = toLocalState(state) | |
return previousLocalState != localState | |
? .merge( | |
effects, additionalEffects( | |
previousLocalState, | |
localState, | |
&state, | |
action, | |
environment | |
) | |
) | |
: effects | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment