v0.3.0
What's Changed
- Introduce
actions
publisher by @gordonbrander in #22 - Introduce KeyedCursorProtocol, remove ViewStore in favor of forward by @gordonbrander in #19
Full Changelog: 0.2.0...v0.3.0
Breaking: removed ViewStore
in favor of forward
ViewStore has been removed in favor of a new child component patter that is closer to vanilla SwiftUI.
The key problem with the ViewStore approach was that the getter for the store value dynamically got the value, meaning that for stores of list items, the state of the store always had to be an Optional. SwiftUI avoids this problem by passing down bare properties to list items. See #19 for more details.
Child components are now handled the way you handle child components in vanilla SwiftUI, with bare state and a send
method.
struct ChildView: View {
var state: ChildModel
var send: (ChildAction) -> Void
var body: some View {
VStack {
Text("Count \(state.count)")
Button(
"Increment",
action: {
store.send(ChildAction.increment)
}
)
}
}
}
To integrate the child view, we can use Address.forward
to create a tagged send function for the child that will translate all child actions into parent actions.
struct ContentView: View {
@StateObject private var store = Store(
state: AppModel(),
environment: AppEnvironment()
)
var body: some View {
ChildView(
state: store.state.child,
send: Address.forward(
send: store.send,
tag: AppChildCursor.tag
)
)
}
}
Breaking: Binding signature change
Bindings have changed from Binding(store:get:tag)
to Binding(get:send:tag:)
. Typical use looks like this:
TextView(
"Placeholder",
Binding(
get: { store.state.text },
send: store.send,
tag: Action.setText
)
)
The old signature relied on ViewStore's conformance to StoreProtocol
. The new signature just requires a getter closure and a send function, so is less opinionated about the specifics of this library.
Actions publisher
Store
now exposes Store.actions
, a publisher which publishes all actions sent to send
. This is useful for logging actions. It is also useful for integrating ObservableStore
with other SwiftUI features, or for wiring together stores in codebases that use multiple stores.
Now both state and actions are published (state already has a publisher through $state
), so it is easy to wired up store events to other SwiftUI features using onReceive
.
Logging example:
.onReceive(store.actions) { action in
// do logging
}