-
Notifications
You must be signed in to change notification settings - Fork 3
Reducer
Abhi Muktheeswarar edited this page Jul 7, 2021
·
1 revision
typealias Reducer<A, S> = (A, S) -> SA reducer is a pure function that takes the current State and an Action to compute a new State. In Flywheel, the reducer lives inside StateReserve.
val reducer = reducerForAction<CounterAction, CounterState> { action, state ->
with(state) {
when (action) {
is CounterAction.IncrementAction -> copy(counter = counter + 1)
is CounterAction.DecrementAction -> copy(counter = counter - 1)
is CounterAction.ResetAction -> copy(counter = 0)
is CounterAction.ForceUpdateAction -> copy(counter = action.count)
else -> state
}
}
}There can be only one reducer associated with a StateReserve. However, we can combine multi reducers to create a root reducer.
By having multiple child reducers, we can have a better separation of concerns. Flywheel comes with two helper functions to combine multiple reducers.
fun <S : State> combineReducers(vararg reducers: Reduce<S>): Reduce<S> =
{ action, state ->
reducers.fold(state, { s, reducer ->
reducer(action, s)
})
}operator fun <S> Reduce<S>.plus(other: Reduce<S>): Reduce<S> = { action, state ->
other(action, this(action, state))
}Example:
val incrementReducer =
reducerForAction<CounterAction.IncrementAction, CounterState> { _, state ->
with(state) { copy(counter = counter + 1) }
}
val decrementReducer =
reducerForAction<CounterAction.DecrementAction, CounterState> { _, state ->
with(state) { copy(counter = counter - 1) }
}
val resetReducer = reducerForAction<CounterAction.ResetAction, CounterState> { _, state ->
with(state) { copy(counter = 0) }
}Using combineReducers
val rootReducer = combineReducers(incrementReducer, decrementReducer, resetReducer)Using plus
val rootReducer = incrementReducer.plus(decrementReducer).plus(resetReducer)If the number of actions that can update the state is less, you can just stick with one reducer.
- A reducer should be a pure function. It means, reducer should only calculate the new state value based on the current
StateandAction. - Reducers are not allowed to modify the existing state. Instead, they must make immutable updates, by copying the existing state and making changes to the copied values. (In
Kotlindata classhelps to achieve this with thecopyfunction). - They must not do any asynchronous logic or other "side effects" like sending analytics event or logging something. Doing so, it violates the rules of a pure function.
- Keep your reducers small by making use of
combineReducersandplushelper functions. - Ideally, avoid iterating over large collections in a reducer, since it makes other actions to wait for a longer period of time in the queue. A better way to do is to, do the iteration and required updates in a
SideEffectanddispatchanActionlikeUpdateMoviesListAction(movies)to set the updated collections.