Skip to content

Latest commit

 

History

History

redukt-thunk

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

ReduKt Thunk

Maven Central GitHub API reference

Adaptation of Redux thunk in ReduKt.

Basics

In ReduKt every thunk is an action that has some logic attached to it and evaluated by thunkMiddleware. There are 2 types of thunks:

  • Associated with regular function that is executed by thunkMiddleware in a blocking manner.
interface Thunk<State> : Action {
    fun DispatchScope<State>.execute()
}
  • Associated with suspending function that is executed by thunkMiddleware in a foreground coroutine.
interface CoThunk<State> : ForegroundJobAction {
    suspend fun DispatchScope<State>.execute()
}

Every thunk has DispatchScope as execute method receiver. It provides closure, dispatch and currentState.

To create a thunk you can simply implement Thunk or CoThunk like this:

data class FetchBook(val id: String) : CoThunk<AppState> {
    suspend fun DispatchScope<AppState>.execute() {
        val client by koin.instance<HttpClient>()
        runCatching { client.get("/book/$id") }
            .onSuccess { dispatch(BookFetchSuccess(it)) }
            .onFailure { dispatch(BookFetchFailed(it)) }
    }
}

You can create thunks as separate types in a more compact way with BaseThunk and BaseCoThunk:

data class FetchBook(val id: String): BaseCoThunk<AppState>({
    val client by koin.instance<HttpClient>()
    runCatching { client.get("/book/$id") }
        .onSuccess { dispatch(BookFetchSuccess(it)) }
        .onFailure { dispatch(BookFetchFailed(it)) }
})

You can also instantiate it directly with Thunk or CoThunk functions:

fun fetchBook(id: String) = CoThunk<AppState> {
    val client by koin.instance<HttpClient>()
    runCatching { client.get("/book/$id") }
        .onSuccess { dispatch(BookFetchSuccess(it)) }
        .onFailure { dispatch(BookFetchFailed(it)) }
}

DispatchList

ReduKt Thunk comes with one handy util called DispatchList. It allows you to wrap multiple actions into a single action. It can be created like this:

val action = DispatchList(listOf(ActionA, ActionB))
// or 
val action = ActionA + ActionB

store.dispatch(action) 
// it results in ActionA and ActionB being dispatched in given order.

DispatchList is a Thunk so it requires thunkMiddleware.

JoiningCoroutinesDispatchList

If any action in DispatchList is a ForegroundJobAction you might want to wait for associated coroutine before dispatching next action. Example below shows how to do it:

val action = JoiningCoroutinesDispatchList(listOf(ActionA, JobActionB, JobActionC))
// or
val action = ActionA + JobActionB + JobActionC support JoiningCoroutines()

store.dispatch(action) 
// It results in ActionA being dispatched normally
// However, JobActionB and JobActionC are dispatched with `joinDispatchJob` in given order.
// It means that their associated coroutines are executed sequentially

It's worth to notice that JoiningCoroutinesDispatchList is a CoThunk so it's executed in foreground coroutine.

JoiningCoroutinesDispatchList has a concurrency flag, that runs associated coroutines concurrently.

val action = JoiningCoroutinesDispatchList(listOf(ActionA, JobActionB, JobActionC), concurrent = true)
// or
val action = ActionA + JobActionB + JobActionC support JoiningCoroutines(concurrent = true)

store.dispatch(action)
// It results in ActionA, JobActionB and JobActionC being dispatched in given order.
// Also, `JoiningCoroutinesDispatchList` waits for coroutines of JobActionB and JobActionC to complete.