Last active
November 24, 2020 05:06
-
-
Save achernoprudov/bbd005c4bbd6833eb2281b1aa8a94cc8 to your computer and use it in GitHub Desktop.
Redux implementation with Combine framework
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
| /// This is peruly marker protocol, | |
| /// it allows us to keep action list open, and add more actions | |
| /// without breaking existed components. | |
| /// | |
| /// Also sometimes it is nice to implement `Codable` or `Equatable` | |
| public protocol Action {} |
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
| import Combine | |
| /// Common Redux reducer contract | |
| public typealias Reducer<State, Action, Environment> = | |
| (inout State, Action, Environment) -> AnyPublisher<Action, Never>? |
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
| import Combine | |
| /// Redux store. | |
| /// | |
| /// For information: https://swiftwithmajid.com/2019/09/18/redux-like-state-container-in-swiftui | |
| /// | |
| /// `State` - module state. | |
| /// `Action` - redux action for communication/modification state | |
| /// `Environment` - abstraction for providing dependencies to reducer | |
| public final class Store<State, Action, Environment>: ObservableObject { | |
| @Published | |
| public private(set) var state: State | |
| private let environment: Environment | |
| private let reducer: Reducer<State, Action, Environment> | |
| private let queue = DispatchQueue(label: "com.skybonds.redux.store", qos: .userInitiated) | |
| private var cancellables: Set<AnyCancellable> = [] | |
| public init( | |
| initialState: State, | |
| reducer: @escaping Reducer<State, Action, Environment>, | |
| environment: Environment | |
| ) { | |
| self.state = initialState | |
| self.reducer = reducer | |
| self.environment = environment | |
| } | |
| public func send(_ action: Action) { | |
| queue.async { | |
| guard let effect = self.reducer(&self.state, action, self.environment) else { | |
| return | |
| } | |
| let cancellable = effect | |
| .sink(receiveValue: self.send) | |
| self.cancellables.insert(cancellable) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment