-
Notifications
You must be signed in to change notification settings - Fork 0
LoadableForEachStore
m-housh edited this page Aug 20, 2021
·
1 revision
A loadable list view that gives the caller access to a ForEachStore
, once the elements have loaded.
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
public struct LoadableForEachStore<
Element: Equatable,
ElementAction: Equatable,
Id: Hashable,
Failure: Error,
Row: View
>: View where Failure: Equatable
Example
// setup types.
public struct User: Equatable, Identifiable {
public let id: UUID = UUID()
public var name: String
public var isFavorite: Bool
public init(name: String, isFavorite: Bool = false) {
self.name = name
self.isFavorite = isFavorite
}
public static let blob = User.init(name: "blob")
public static let blobJr = User.init(name: "blob-jr")
public static let blobSr = User.init(name: "blob-sr")
}
extension Array where Element == User {
public static let users: Self = [.blob, .blobJr, .blobSr]
}
public enum UserAction: Equatable {
case binding(BindingAction<User>)
}
public let userReducer = Reducer<User, UserAction, Void>.empty
.binding(action: /UserAction.binding)
public enum LoadError: Error, Equatable {
case loadingFailed
}
// Create the environment dependency.
extension LoadableForEachEnvironment where
Element == User,
Id = User.ID,
LoadRequest = EmptyLoadRequest,
Failure == LoadError
{
state let live = Self.init(
load: { _ in
Just(.init(uniqueElements: .users))
.delay(for: .seconds(1), scheduler: DispatchQueue.main) // simulate loading.
.setFailureType(to: LoadError.self)
.eraseToEffect()
},
mainQueue: .main
)
}
// Create the reducer.
let appReducer = Reducer<
LoadableForEachStateFor<User, LoadError>,
LoadableForEachStoreActionFor<User, UserAction, LoadError>,
LoadableForEachEnvironmentFor<User, LoadError>
>.empty
.loadableForEachStore(
state: \.self,
action: /LoadableForEachAction.self,
environment: { $0 },
forEach: userReducer
)
// Use the for each view, you would typically not create the store inside the body, but just
// an example of what it looks like.
struct AppView: View {
var body: some View {
LoadableForEachStore(
store: .init(
initialState: .init(),
reducer: appReducer,
environment: .live
)
) { store in
WithViewStore(store) { viewStore in
HStack {
Text(viewStore.name)
Spacer()
Toggle(
"Favorite"
isOn: viewStore.binding(keyPath: \.isFavorite, send: UserAction.binding)
)
}
}
}
}
}
View
Create a new loadable list view.
public init(
store: Store<
LoadableForEachState<Element, Id, Failure>,
LoadableForEachAction<Element, ElementAction, Id, Failure>
>,
autoLoad: Bool = true,
@ViewBuilder content row: @escaping (Store<Element, ElementAction>) -> Row
)
- store: The store for the view state.
- autoLoad: Whether we automatically load items when the view first appears.
- row: The view builder for an individual row in the list.
The store for our state and actions.
public let store:
Store<
LoadableForEachState<Element, Id, Failure>,
LoadableForEachAction<Element, ElementAction, Id, Failure>
>
public var body: some View
Generated at 2021-08-23T22:43:49+0000 using swift-doc 1.0.0-rc.1.
Types
- EditButton
- EditMode
- EditModeAction
- EmptyLoadRequest
- ListAction
- LoadError
- Loadable
- LoadableAction
- LoadableEnvironment
- LoadableForEachAction
- LoadableForEachEnvironment
- LoadableForEachState
- LoadableForEachStore
- LoadableList
- LoadableListAction
- LoadableListEnvironment
- LoadableListState
- LoadablePicker
- LoadablePickerAction
- LoadablePickerEnvironment
- LoadablePickerState
- LoadableView
- User
- UserAction