Skip to content

Commit

Permalink
Reorder update signature to State, Action, Environment (#14)
Browse files Browse the repository at this point in the history
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<State, Environment, Action>` to `Store<State, Action, Environment>`

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.
  • Loading branch information
gordonbrander authored Mar 26, 2022
1 parent f21ef24 commit 546c7d0
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 17 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ struct AppState: Equatable {
/// State update function
static func update(
state: AppState,
environment: AppEnvironment,
action: AppAction
action: AppAction,
environment: AppEnvironment
) -> Update<AppState, AppAction> {
switch action {
case .increment:
Expand Down Expand Up @@ -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>
(State, Action, Environment) -> Update<State, Action>
```

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).
Expand Down Expand Up @@ -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<State, Action> {
switch action {
// ...
Expand All @@ -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<State, Action> {
switch action {
// ...
Expand Down
12 changes: 6 additions & 6 deletions Sources/ObservableStore/ObservableStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<State, Environment, Action>: ObservableObject
public final class Store<State, Action, Environment>: ObservableObject
where State: Equatable {
/// Stores cancellables by ID
private(set) var cancellables: [UUID: AnyCancellable] = [:]
Expand All @@ -112,8 +112,8 @@ where State: Equatable {
/// Update function for state
public var update: (
State,
Environment,
Action
Action,
Environment
) -> Update<State, Action>
/// Environment, which typically holds references to outside information,
/// such as API methods.
Expand All @@ -134,8 +134,8 @@ where State: Equatable {
public init(
update: @escaping (
State,
Environment,
Action
Action,
Environment
) -> Update<State, Action>,
state: State,
environment: Environment
Expand Down Expand Up @@ -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`
Expand Down
8 changes: 4 additions & 4 deletions Tests/ObservableStoreTests/ObservableStoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, Action> {
switch action {
case .increment:
Expand Down Expand Up @@ -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<Self, Action> {
switch action {
case .setTitle(let title):
Expand Down

0 comments on commit 546c7d0

Please sign in to comment.