Yet another UDF state management lib
This repo has been moved to Puredux monorepo. Follow the installation guide there.
If you're looking to contribute or raise an issue, head over to the main repository where it's being developed now.
PureduxStore is available as a part of Puredux via Swift Package Manager. To install it, in Xcode 11.0 or later select File > Swift Packages > Add Package Dependency... and add Puredux repositoies URLs for the modules requried:
https://github.com/KazaiMazai/Puredux
import PureduxStore
let initialState = AppState()
and Action
protocol:
protocol Action {
}
let reducer: (inout AppState, Action) -> Void = { state, action in
//mutate state here
}
let factory = StoreFactory<AppState, Action>(
initialState: initialState,
reducer: reducer
)
let store = factory.rootStore()
Let's have an AsyncAction
protocol defined as:
protocol AsyncAction: Action {
func execute(completeHandler: @escaping (Action) -> Void)
}
and some long running action that with injected service:
struct SomeAsyncAction: AsyncAction {
@DI var service: SomeInjectedService
func execute(completeHandler: @escaping (Action) -> Void) {
service.doTheWork {
switch $0 {
case .success(let result):
completeHandler(SomeResultAction(result))
case .success(let error):
completeHandler(SomeErrorAction(error))
}
}
}
}
Execute side effects in the interceptor:
let storeFactory = StoreFactory<AppState, Action>(
initialState: initialState,
interceptor: { action, dispatch in
guard let action = ($0 as? AsyncAppAction) else {
return
}
DispatchQueue.main.async {
action.execute { dispatch($0) }
}
},
reducer: reducer
)
let scopedStore: Store<SubState, Action> = storeFactory.scopeStore { appState in appState.subState }
let observer = Observer<SubState> { substate, completeHandler in
// Handle your latest state here and dispatch some actions to the store
scopedStore.dispatch(SomeAction())
guard wannaKeepReceivingUpdates else {
completeHandler(.dead)
return
}
completeHandler(.active)
}
scopedStore.subscribe(observer: observer)
let childStoreObject: StoreObject<(AppState, LocalState), Action> = storeFactory.childStore(
initialState: LocalState(),
reducer: { localState, action in
localState.reduce(action: action)
}
)
let childStore = childStoreObject.store()
let observer = Observer<(AppState, LocalState)> { stateComposition, complete in
// Handle your latest state here and dispatch some actions to the store
childStore.dispatch(SomeAction())
guard wannaKeepReceivingUpdates else {
completeHandler(.dead)
return
}
completeHandler(.active)
}
childStore.subscribe(observer: observer)
Old API will be deprecated in the next major release. Please consider migration to the new API.
RootStore
to StoreFactory
:Before:
let rootStore = RootStore<AppState, Action>(
queue: StoreQueue = .global(qos: .userInteractive)
initialState: initialState,
reducer: reducer
)
let store: Store<AppState, Action> = rootStore.store()
Now:
let storeFactory = StoreFactory<AppState, Action>(
initialState: initialState,
qos: .userInteractive,
reducer: reducer
)
let store: Store<AppState, Action> = storeFactory.rootStore()
MainQueue is not available for Stores any more. Since now, stores always operate on a global serial queue with configurable QoS.
Before:
rootStore.interceptActions { action in
guard let action = ($0 as? AsyncAppAction) else {
return
}
DispatchQueue.main.async {
action.execute { store.dispatch($0) }
}
}
Now:
let storeFactory = StoreFactory<AppState, Action>(
initialState: initialState,
interceptor: { action, dispatched in
guard let action = ($0 as? AsyncAppAction) else {
return
}
DispatchQueue.main.async {
action.execute { dispatch($0) }
}
},
reducer: reducer
)
proxy(...)
to scope(...)
:Before:
let storeProxy = rootStore.store().proxy { appState in appState.subState }
Now:
let scopeStore = storeFactory.scopeStore { appState in appState.subState }
StoreFactory is a factory for Stores and StoreObjects. It suppports creation of the following store types:
(Root, Local) -> Composition
state mapping and it's own lifecycleuserInteractive
quality of service. QoS can be changed.Call store observer's complete handler with dead status:
let observer = Observer<State> { state, completeHandler in
//
completeHandler(.dead)
}
It does both. Puredux allows to have a single store that can be scoped to proxy substores for sake of features isolation. It also allows to have a single root store with multiple plugable child stores for even deeper features isolation.
Puredux is designed in a way that you can seamlessly scale up to multiple stores when needed.
rootStore()
methodRoot store object lifecycle and its state managed by factory. Initalized together with the factory and released when factory is released It exist as long as the factory exist.
let store = factory.rootStore()
No. State is initialized when factory is created. Then it lives together with it. Typically factory's' lifecycle matches app's lifecycle.
let scopedStore: Store<Substate, Action> = storeFactory.scopeStore { appState in appState.subState }
StoreFactory allows to create child stores. You should only provide initial state and reducer:
let childStoreObject: StoreObject<(AppState, LocalState), Action> storeFactory.childStore(
initialState: LocalState(),
reducer: { localState, action in
localState.reduce(action: action)
}
)
Child store is a StoreObject
it will exist while you keep a strong reference to it.
StoreObject<State, Action>
?Root store's and scope store's lifecycle is controlled by StoreFactory. They exist while factory exist. Typically during the whole app lifecycle.
Child store is for the cases when we want to take over the control of the store lifecycle. Typically when we present screens or some flows of the app.
StoreObject<State, Action>
prevents from errors that could occur because of confusion with
Store<State, Action
First of all it follows the rules:
According to the rules above.
When action is dispatched to RootStore:
When action is dispatched to ChildStore:
PureduxStore is licensed under MIT license.
link |
Stars: 15 |
Last commit: 6 weeks ago |
This release introduces new API with a StoreFactory on top of it. It also brings a possibility to build Parent-Child store hierarchy with child stores.
The old API is only marked as deprecated and will be removed in future.
Documentation was updated.
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics