LoginSignup
3
2

Kotlin/JSのハマりポイント!【随時更新】

Last updated at Posted at 2022-12-26

忘備録的な感じで残しておきます
なんかわかれば追加するかもです

↑実際にKotlin/JSで作成したポートフォリオのようなものです。

本記事はkotlin-wrappers 1.0.0-pre.545を対象として書かれています。

kotlin-wrappersはこれからの更新でも大量の破壊的変更が伴うことが予想されるため、バージョンが少しでも違う場合はこの記事を参考にしないほうがいい可能性があります。

[React Router] BrowserRouterが使えない!?

WebpackConfigでdevServer内のhistoryApiFallbackをtrueにする必要があるのですが、build.gradle.kts内のcommonWebpackConfigから変更することができないためwebpack.config.d/webpack.config.jsを作成し、

if (config.devServer){
    //上書きしないようassign
    config.devServer = Object.assign(config.devServer, {
        historyApiFallback: true,
    });
}

このように書きます。

[Emotion] styled('xxx')((...) => ...)←どう書くんや

MUIのAppBarのpositionをfixedにするときに困りました

const Offset = styled('div')(({ theme }) => theme.mixins.toolbar);

↓Kotlin/JSではこのように書きます

val Offset = div.styled {
     +it.asDynamic().theme.unsafeCast<mui.material.styles.Theme>().mixins.toolbar.unsafeCast<Properties>()
}

+Properties?.unaryPlus()を呼び出しています。

sealed class PropertiesBuilder :
    Properties,
    RuleBuilder<PropertiesBuilder>,
    PseudosRuleBuilder<PropertiesBuilder> {
    //↓おまえか!?!?!?
    inline operator fun Properties?.unaryPlus() {
        Object.assign(this@PropertiesBuilder, this)
    }
}

キャストしないとIntelliJくんがProperties?.unaryPlus()出してくれないので罠ですこれ。

[React] PropsにReactNodeを渡したい!!!!

こんな感じでcreateをつけましょう

CardHeader {
    title = Typography.create {
        variant = TypographyVariant.h6
        +it.name
    }
}

前はcreateElement{}で囲むとできた

Node.jsをダウンロードしたくない!/ バージョンを変えたい!

build.gradle.ktsに追記しましょう

build.gradle.kts
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
    rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().run {
        download = true // デフォルトの挙動 falseで既にインストールされているNode.jsを使う
        nodeVersion = "16.15.0" // ここにNode.jsのバージョン
    }
}

[MUI] <Grid xs={...}/>みたいなやつ

this.asDynamic()で無理やりできます。

Grid {
    item = true
    asDynamic().sm = 6
    asDynamic().xs = 12
    //...
}

asDynamic().component = "label"とかもできます。
対応するプロパティが見つからなかったら、断腸の思いでこれを使いましょう。
Kotlin/JSの意味・・・

npmパッケージの関数を自分でラップして使う

公式でも説明されていますが・・・
usehooks-ts

を使ってみます。

npmの依存関係を書く

build.gradle.kts
dependencies {
    // ・・・
+    implementation(npm("usehooks-ts", "2.8.0"))
    // ・・・
}

書く

src/main/kotlin/usehooksみたいなディレクトリを作ってそこに入れるような感じに私はしています。
今回使用するのはuseDarkModeなのでuseDarkMode.ktを作り、ここを見ながら書いていきます

useDarkMode.kt
@file:JsModule("usehooks-ts")
@file:JsNonModule

package usehooks

@JsName("useDarkMode")
external fun useDarkMode(defaultValue: Boolean? = definedExternally): UseDarkModeOutput

external interface UseDarkModeOutput {
    val isDarkMode: Boolean
    val toggle: () -> Unit
    val enable: () -> Unit
    val disable: () -> Unit
}

正解かはわかりませんがこのように書いたら動きました。

CSSとかのNoneが無い!!

あります。

完全修飾None
web.cssom.None.Companion.none

です。
Auto.autoもあります。

Button{
    css { 
        display=None.none
    }
    +"みえないボタン"
}

どのdocumentだよ!!!!!!

これはKotlin/JSあるあるですね。
安易にkotlin-wrappersのバージョンを上げるとパッケージ名が変わったりして時代に置いていかれます。

import react.create
import react.dom.client.createRoot
import web.dom.document

fun main() {
    val container = document.createElement("div").also {
        document.body.appendChild(it)
    }

    createRoot(container).render(
        App.create()
    )
}

このようなよく見るコードのdocumentですが、補完で2つのdocumentが出てきますよね。

web.dom.document
kotlinx.browser.document

これを間違えると、document.bodyがNullableになったり、createRootで型が違うと怒られます。
先程のコードの場合は上のweb.dom.documentが正解です。
下のkotlinx.browser.documentは使う場面あるんですかね・・?

どのwindowだよ!!!!!!

kotlinx-coroutinesWindow.asCoroutineDispatcher()を使うときは、

kotlinx.browser.window.asCoroutineDispatcher()

です。
クラス Windowには以下の2種類あり、それぞれ別の場所からアクセスできます。

org.w3c.dom.Window //→ kotlinx.browser.window
web.window.Window  //→ web.window.window

asCoroutineDispatcher()org.w3c.dom.Windowに対して使うのでkotlinx.browser.windowです。

[MUI] <Button component={Link}/> componentが無い!

足りないものは自分で作り出しましょう。

var ButtonProps.component :  ElementType<*>?
    get() =  unsafeCast<PropsWithComponent>().component
    set(value) { unsafeCast<PropsWithComponent>().component=value}
//例
Button{
    component=Link
}
3
2
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
3
2