Компонент app

fun main() {
    val container = document.getElementById("root")!!
    createRoot(container).render(app.create())
}

val app = FC<Props> ("App"){
    QueryClientProvider {
        client = QueryClient()
        containerStudentList {}
    }
}

Компонент containerStudentList

val containerStudentList = FC<Props>("QueryStudentList") {
    val query = useQuery<String, QueryError, String, QueryKey>(
        queryKey = arrayOf("studentList").unsafeCast<QueryKey>(),
        queryFn = {
            fetchText(Config.studentsPath)
        }
    )
    ...

Компонент containerStudentList

val containerStudentList = FC<Props>("QueryStudentList") {
    val query = useQuery ...
    if (query.isLoading) div { +"Loading .." }
    else if (query.isError) div { +"Error!" }
    else {
        val items =
            Json.decodeFromString<Array<Student>>(query.data ?: "")
        CStudentList {
            students = items
        }
    }
}

Promise

public open external class Promise<out T>(
    executor: (
        resolve: (T) -> Unit, 
        reject: (Throwable) -> Unit
    ) -> Unit
)

Цепочка Promise

public open external class Promise<out T>(..)
    public open fun <S> then(
        onFulfilled: ((T) -> S)?
    ): Promise<S>

Вложенный Promise

inline fun <T, S> Promise<Promise<T>>.then(
    noinline onFulfilled: ((T) -> S)?
): Promise<S> {
    return this.unsafeCast<Promise<T>>().then(onFulfilled)
}

fetch

@JsModule("cross-fetch")
@JsNonModule
external fun fetch(
    url: String,
    options: Options = definedExternally
): Promise<Response>
Fetch_API

fetch()

Response

external interface Response {
    fun json(): Promise<dynamic>
    fun text(): Promise<String>
}
Response

Options

external interface FetchOptions {
    var method: String
    var headers: dynamic
    var body: dynamic
}

fetchText

fun fetchText(
    url: String,
    options: Options = jso()
) =
    fetch(url, options)
        .then { it.text() } // Promise<Promise<String>>
        .then { it }        // Promise<String>

CStudentList

val CStudentList = FC<StudentListProps>("StudentList") 
    { props ->
        ol {
            props.students.forEach { student ->
                li {
                    CStudentItem {
                        this.student = student
                    }
                } 
            } 
        } 
    }