LoginSignup
1
0

More than 1 year has passed since last update.

Kotlin/JSで作ったReact HooksをTypeScriptから使う

Last updated at Posted at 2021-08-04

概要

Kotlin/JSでReactのカスタムフックを作成し、TypeScript用の型定義ファイルを生成します。
とりあえずTypeScriptから使えた程度の出来でまだ詳細は把握しきれておらず、実用性は皆無です。
Kotlin側のコードはKotlin/JSで直接Reactを使う場合でも同じく有効です。

下記の記事から分かる通り現時点で(2021/08/03)IRバックエンドはalphaなので、慎重に利用してください。
https://kotlinlang.org/docs/components-stability.html

Kotlin/JSを使う

Kotlin/JSのコードから型定義ファイル(.d.ts)を生成するためには、@JsExportを適用する必要があります。
しかし、プリミティブしかJavaScriptから取り扱うことができないため、いくら型定義ファイルを生成しても、JavaScriptから高度なライブラリを操作することはかなり厳しいです。

そこで、Ktolin/JSでラップすることで間接的に表現することができます。
本記事ではその例としてReact HooksとKotlin coroutinesの組み合わせを挙げています。

コード

Kotlin

build.gradle.kts
plugins {
    kotlin("js") version "1.5.30-M1"
}

group = "com.uramnoil"
version = "0.1.0"

repositories {
    mavenCentral()
}

val kotlinVersion = "1.5.21"
val reactVersion = "17.0.2"

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1")
    implementation("org.jetbrains.kotlin-wrappers:kotlin-react:17.0.2-pre.224-kotlin-1.5.21")
    implementation(peerNpm("react", reactVersion))}

kotlin {
    js(IR) {
        binaries.library()
        browser()
    }
}
hooks.kt
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import react.useState

val flow = MutableStateFlow(0)

@JsExport
fun useHoge(): String {
    var hoge by useState(flow.value)

    useEffectOnce {
        GlobalScope.launch { // NOTE: Dangerous API
            flow.collect {
                hoge = it
            }
        }
    }

    return hoge.toString()
}

// Flow操作用
@JsExport
fun increment() {
    flow.value++
}

TypeScript

package.json
{
    "dependencies": {
        "project-root-name": "link:/folder/to/ProjectRoot/build/js/packages/project-root-name"
    }
}
App.tsx
import "./App.css";
import { increment, useHoge } from "kotlin-react-library-sample";

function App() {
  const hoge = useHoge();

  return (
    <div className="App">
      {hoge}
      <button onClick={() => increment()}>hoge</button>
    </div>
  );
}

export default App;

サンプル

画面収録.gif

普通に動きます。

まとめ

ViewModelを扱うReact Hooksを作っておけば、Kotlin/Multiplatformでロジックを共通化していてもTypeScriptでフロントエンドを作れるようになります。

もう少し調査してみて記事を書いてみたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0