From 546c7d013ea8631c0d3949ee831f032f2fdc3cc3 Mon Sep 17 00:00:00 2001 From: Gordon Brander Date: Sat, 26 Mar 2022 11:02:25 -0700 Subject: [PATCH] Reorder update signature to State, Action, Environment (#14) This PR changes the order of update function arguments: - Changes update function signature from `update(State, Environment, Action)` to `update(State, Action, Environment)` - Changes Store from `Store` to `Store` Why? - This order of arguments is used by two other Elm-like libraries: [Swift Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture) and [Redux-like state container](https://swiftwithmajid.com/2019/09/18/redux-like-state-container-in-swiftui/). - Context arguments like environment often seem to be passed last in Swift. E.g. [`UIViewRepresentable.Context`](https://developer.apple.com/documentation/swiftui/uiviewrepresentable/updateuiview(_:context:)) is passed last to methods in SwiftUI. - State and Action are always used, but Environment might be nil, or an empty struct. You don't always need environment. It is optional. - The order reads better in the signature, since state and action are always paired together in update function and `Update` struct. --- README.md | 14 +++++++------- Sources/ObservableStore/ObservableStore.swift | 12 ++++++------ .../ObservableStoreTests.swift | 8 ++++---- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1031f7a..3150ff9 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ struct AppState: Equatable { /// State update function static func update( state: AppState, - environment: AppEnvironment, - action: AppAction + action: AppAction, + environment: AppEnvironment ) -> Update { switch action { case .increment: @@ -77,7 +77,7 @@ A `Store` is a source of truth for application state. It's an [ObservableObject] Store exposes a single [`@Published`](https://developer.apple.com/documentation/combine/published) property, `state`, which represents your application state. `state` is read-only, and cannot be updated directly. Instead, like Elm or Redux, all `state` changes happen through a single `update` function, with the signature: ``` -(State, Environment, Action) -> Update +(State, Action, Environment) -> Update ``` The `Update` returned is a small struct that contains a new state, plus any optional effects and animations associated with the state transition (more about that in a bit). @@ -171,8 +171,8 @@ You can subscribe to an effects publisher by returning it as part of an Update: ```swift func update( state: State, - environment: Environment, - action: Action + action: Action, + environment: Environment ) -> Update { switch action { // ... @@ -196,8 +196,8 @@ Use `Update.animation` to set an explicit [Animation](https://developer.apple.co ```swift func update( state: State, - environment: Environment, - action: Action + action: Action, + environment: Environment ) -> Update { switch action { // ... diff --git a/Sources/ObservableStore/ObservableStore.swift b/Sources/ObservableStore/ObservableStore.swift index 5dccc6f..d650de9 100644 --- a/Sources/ObservableStore/ObservableStore.swift +++ b/Sources/ObservableStore/ObservableStore.swift @@ -102,7 +102,7 @@ where State: Equatable { /// See https://guide.elm-lang.org/architecture/ /// and https://guide.elm-lang.org/webapps/structure.html /// for more about this approach. -public final class Store: ObservableObject +public final class Store: ObservableObject where State: Equatable { /// Stores cancellables by ID private(set) var cancellables: [UUID: AnyCancellable] = [:] @@ -112,8 +112,8 @@ where State: Equatable { /// Update function for state public var update: ( State, - Environment, - Action + Action, + Environment ) -> Update /// Environment, which typically holds references to outside information, /// such as API methods. @@ -134,8 +134,8 @@ where State: Equatable { public init( update: @escaping ( State, - Environment, - Action + Action, + Environment ) -> Update, state: State, environment: Environment @@ -232,7 +232,7 @@ where State: Equatable { /// `.receive(on: DispatchQueue.main)`). public func send(_ action: Action) { // Generate next state and effect - let next = update(self.state, self.environment, action) + let next = update(self.state, action, self.environment) // Set `state` if changed. // // Mutating state (a `@Published` property) will fire `objectWillChange` diff --git a/Tests/ObservableStoreTests/ObservableStoreTests.swift b/Tests/ObservableStoreTests/ObservableStoreTests.swift index f5fdee5..ed69ccc 100644 --- a/Tests/ObservableStoreTests/ObservableStoreTests.swift +++ b/Tests/ObservableStoreTests/ObservableStoreTests.swift @@ -29,8 +29,8 @@ final class ObservableStoreTests: XCTestCase { /// State update function static func update( state: Self, - environment: Environment, - action: Action + action: Action, + environment: Environment ) -> Update { switch action { case .increment: @@ -214,8 +214,8 @@ final class ObservableStoreTests: XCTestCase { /// Update function for Fx tests (below) static func update( state: Self, - environment: Environment, - action: Action + action: Action, + environment: Environment ) -> Update { switch action { case .setTitle(let title):