Skip to content

mercari/RxReduxK

Repository files navigation

RxRedux for Kotlin

jcenter Build Status

Micro-framework for Redux implemented in Kotlin

Installation

dependencies {
  repositories {
    jcenter()
  }
}

implementation("com.mercari.rxredux:rxredux:<latest-version>")

Usage

This framework is composed of several types/abstractions inspired by Redux that help to implement the reactive behavior of application components. It is based on RxJava for reactivity and works well with RemoteDataK.

State

State represents the model or state of your component or UI. A State is recommended to be immutable, however it can be allowed to be mutable.

This can typically be implemented by a data class

For example:

data class CounterState(
    val counter: Int
) : State

Action

An Action represents the desired modifications on a State, for example

class Increment : Action
class Decrement : Action

Although not required, it is recommended to model Actions as class hierarchy with a sealed class.

sealed class CounterAction : Action

class Increment : CounterAction()
class Decrement : CounterAction()

An Action can contain parameters that make them more useful depending on the desired behaviour. For example:

class Increment(val by: Int) : CounterAction

Actions are to be dispatched through the Store's dispatch method to perform State mutations.

For example:

store.dispatch(Increment(2))

Reducer

A Reducer is where the State is mutated or modified, depending on which Action is applied. It is basically a map of the desired modifications and their effects.

For example:

class CounterReducer: Reducer<CounterState, CounterAction> {
    override fun reduce(currentState: CounterState, action: CounterAction) : CounterState =
        when(action) {
          is Increment -> CounterState(counter: currenState.counter + action.by)
          is Decrement -> CounterState(counter: currenState.counter - action.by)
        }
}

Middleware

Middleware allows for a variety of behaviours that are not directly related to the component's State. This is useful for the implementation of so called cross-cutting concerns such as Logging, by hooking into the sequence of Action events.

Middleware can run before reducing the state or after depending on the need, this can be achieved by overriding the provided methods.

Store

The Store "stores" the State, and exposes it for observation as an Observable. It also connects all the other abstractions together.

To create a Store, simply instantiate it with an initial State and its related Reducer:

val counterStore = Store(initialState, reducer)

Several middleware can also be added to the Store through the Store's addMiddleware method.

Examples

Examples of usage can be seen in the tests