Name: RxState
Owner: RxSwift Community
Description: Redux implementation in Swift using RxSwift
Created: 2017-05-12 07:37:59.0
Updated: 2018-05-18 20:50:47.0
Pushed: 2017-10-22 21:43:38.0
Size: 523
Language: Swift
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
RxState a predictable state container for Swift apps. It's a tiny library built on top of RxSwift and inspired by Redux that facilitates building Unidirectional Data Flow architecture.
App State: A single immutable data structure. It includes the UI state, the navigation state and the state of your model layer.
Store:Contains the app state and notifies the App State Observers
of the App State
updates.
Reducer: A pure function that takes the current app state and an Action
as input, creates a new App State
that reflects the changes described by the Action
, and returns the new App State
.
Action: Actions describe a state change. The only way to modified the App State
is by dispatching Actions
to the Store
.
Action Creators and Dispatchers: Creates Action
s and dispatch them to the store.
App State Observers: Observers the App State
in the Store
to transform it to presentable data, write logs, etc.
View: Presents the presentable data that was deriver from the App State
and delivers the user's interactions to the Action Creators and Dispatchers
.
The View/View Controller
sends events (The View Model
's inputs) to the View Model
.
The View Model
creates an Action
from the received inputs and dispatch them to the Store
.
The View Model
can use a dedicated Action Creator
s to create Action
s.
Action Creator
s do can async work and, based on the results it gets, returns different Action
s to the View Model
to dispatch.
The Store
sends the App State
and the received Action
to the Reducer
.
The Reducer
receives the current App State
and the dispatched Action
, computes and returns new App State
.
The Store
sends the new App State
to the subscribers.
One of the subscribers could be a Middleware
that logs the App State
resulted from dispatching an Action
.
The View Model
receives the new App State
, transform it presentable data, and send it to the View/View Controller
.
The View Model
can use Transformer
s to transform the App State
to presentable data. This helps you reuse the transformation code in different View Model
s.
The View/View Controller
render the UI to show the presentable data to the user.
RxState defines the main component for you:
Store
: Contains the App State
in the form of Driver<[SubstateType]>
.
SubstateType
: A protocol that tags structs representing a substate.
Ex.
ct TasksState: SubstateType {
var tasks: [Task]
var addingTask: Bool
You can add a Substate
s to the App State
by dispatching StoreAction.add(states: [SubstateType])
.
tasksState = TasksState()
action = StoreAction.add(states: [tasksState])
e.dispatch(action: action)
ActionType
: A protocol that tags an Action
. The Store
has the following Action
s:ic enum StoreAction: ActionType {
/// Adds substates to the application state.
case add(states: [SubstateType])
/// Removes all substates in the application state.
case reset
MainReducer
: A reducer used by the Store
's dispatch function to call the respective reducer based on the Action type.mainReducer: MainReducer = { (state: [SubstateType], action: ActionType) -> [SubstateType] in
// Copy the `App State`
var state: [SubstateType] = state
// Cast to a specific `Action`.
switch action {
case let action as TasksAction:
// Extract the `Substate`.
guard var (tasksStateIndex, tasksState) = state
.enumerated()
.first(where: { (_, substate: SubstateType) -> Bool in
return substate is Store.TasksState}
) as? (Int, Store.TasksState)
else {
fatalError("You need to register `TasksState` first")
}
// Reduce the `Substate` to get a new `Substate`.
tasksState = Store.reduce(state: tasksState, action: action)
// Replace the `Substate` in the `App State` with the new `Substate`.
state[tasksStateIndex] = tasksState as SubstateType
default:
fatalError("Unknown action type")
}
// Return the new `App State`
return state
MiddlewareType
: A protocol defining an object that can observe the App State
and the last dispatched Action
and does something with it like logging:ocol LoggingMiddlewareType: Middleware, HasDisposeBag {}
l class LoggingMiddleware: LoggingMiddlewareType {
var disposeBag = DisposeBag()
func observe(currentStateLastAction: Driver<CurrentStateLastAction>) {
currentStateLastAction
.drive(
onNext: { (currentState: [SubstateType], lastAction: ActionType?) in
print(currentState)
print(lastAction)
}, onCompleted: nil, onDisposed: nil)
.disposed(by: disposeBag)
}
}
'RxState'
I have tried to make the demo app as comprehensive as possible. It currently runs on iOS and macOS. Notice how, because of the architecture, only the View/ View Controller layer needed to change in order to port the app from iOS to macOS.
We would love to see you involved and feedback and contribution are greatly appreciated :) Checkout the Contributing Guide.
Nazih Shoura, shoura.nazeeh@gmail.com
This library belongs to RxSwiftCommunity.
RxState is available under the MIT license. See the LICENSE file for more info.