jsMain.com.zegreatrob.react.dataloader.DataLoader.kt Maven / Gradle / Ivy
package com.zegreatrob.react.dataloader
import com.zegreatrob.minreact.reactFunction
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import react.*
typealias DataLoadFunc = suspend (DataLoaderTools) -> D
@Deprecated(
replaceWith = ReplaceWith("DataLoaderProps"),
level = DeprecationLevel.WARNING,
message = "Name to be removed."
)
typealias DataLoadWrapperProps = DataLoaderProps
data class DataLoaderProps(
val getDataAsync: DataLoadFunc,
val errorData: (Throwable) -> D,
val scope: CoroutineScope? = null,
val children: RBuilder.(value: DataLoadState) -> Unit
) : Props
private val cachedComponent = reactFunction> { props ->
val (getDataAsync, errorData, injectedScope) = props
val (state, setState) = useState> { EmptyState() }
val scope = injectedScope ?: useScope("Data load")
if (state is EmptyState) {
startPendingJob(scope, setState, getDataAsync, errorData)
}
props.children(this, state)
}
fun dataLoader() = cachedComponent.unsafeCast>>()
fun RBuilder.dataLoader(
getDataAsync: DataLoadFunc,
errorData: (Throwable) -> D,
scope: CoroutineScope? = null,
children: RBuilder.(DataLoadState) -> Unit = {}
) = child(dataLoader(), DataLoaderProps(getDataAsync, errorData, scope, children)) {}
private fun startPendingJob(
scope: CoroutineScope,
setState: StateSetter>,
getDataAsync: DataLoadFunc,
errorData: (Throwable) -> D
) {
val setEmpty = setState.empty()
val setPending = setState.pending()
val setResolved = setState.resolved()
val tools = DataLoaderTools(scope, setEmpty)
setPending(
scope.launch { getDataAsync(tools).let(setResolved) }
.also { job -> job.errorOnJobFailure(setResolved, errorData) }
)
}
private fun Job.errorOnJobFailure(setResolved: (D) -> Unit, errorResult: (Throwable) -> D) =
invokeOnCompletion { cause -> if (cause != null) setResolved(errorResult(cause)) }
private fun StateSetter>.empty(): () -> Unit = {
this(
EmptyState()
)
}
private fun StateSetter>.pending(): (Job) -> Unit = {
this(
PendingState()
)
}
private fun StateSetter>.resolved(): (D) -> Unit = {
this(
ResolvedState(it)
)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy