jsMain.com.zegreatrob.react.dataloader.DataLoader.kt Maven / Gradle / Ivy
package com.zegreatrob.react.dataloader
import com.zegreatrob.minreact.DataProps
import com.zegreatrob.minreact.TMFC
import com.zegreatrob.minreact.tmFC
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import react.ChildrenBuilder
import react.StateSetter
import react.useState
typealias DataLoadFunc = suspend (DataLoaderTools) -> D
@Deprecated(
replaceWith = ReplaceWith("DataLoaderProps"),
level = DeprecationLevel.WARNING,
message = "Name to be removed."
)
typealias DataLoadWrapperProps = DataLoader
typealias DataLoaderProps = DataLoader
data class DataLoader(
val getDataAsync: DataLoadFunc,
val errorData: (Throwable) -> D,
val scope: CoroutineScope? = null,
val children: ChildrenBuilder.(value: DataLoadState) -> Unit
) : DataProps> {
override val component = cachedComponent.unsafeCast>>()
}
private val cachedComponent = tmFC> { 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>>()
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