Skip to content

Instantly share code, notes, and snippets.

@manmal
Last active June 21, 2021 18:17
Show Gist options
  • Save manmal/be3a3ffa36de8614709e5531fc753c79 to your computer and use it in GitHub Desktop.
Save manmal/be3a3ffa36de8614709e5531fc753c79 to your computer and use it in GitHub Desktop.
On-change handlers for Composable Architecture Reducers
// 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