Path

Home / Kotlin/JS + React の Tips (pre.258)

Last updated

2021/10/26

本文

pre.258 時点での情報です。 JetBrains/kotlin-wrappers は頻繁に更新されているため、最新の情報を得るには実装を確認する必要があります。

component を作成する

React component は、 RComponent を継承したクラスを作成します。

external interface MyComponentProps : Props
external interface MyComponentState : State
class MyComponentRComponent : RComponent<MyComponentProps, MyComponentState>() {
    override fun RBuilder.render() {
    }
}
val MyComponent: ComponentClass<MyComponentProps> = MyComponentRComponent::class.react

カスタムタグを利用する

HTML の要素であれば、定義されたタグを利用することができます。一方、例えば SVG の要素など、宣言されていないタグを利用したいケースもあります。そのときは、タグを生成するメソッドを定義することで実現できます。

fun RBuilder.tag(tagName: String, block: RDOMBuilder<HTMLTag>.() -> Unit) {
    tag(block) {
        HTMLTag(
            tagName = tagName,
            consumer = it,
            initialAttributes = mapOf(),
            namespace = null,
            inlineTag = true,
            emptyTag = false,
        )
    }
}

定義した RBuilder.tag は、次のように利用します。

tag("path") {
    attrs["d"] = "M 1 1 L 2 1 L 2 2 L 1 2"
}

React router を利用する

次は、 React router を利用する例です。

BrowserRouter {
    Switch {
        Route {
            attrs.component = Home
            attrs.exact = true
            attrs.path = arrayOf("/")
        }
    }
}

React router にある historylocation などは RouteComponentProps で定義されています。 Route で指定される component であれば、 .react で得られる ComponentClass<P> で動作します。

external interface HomeProps : Props, RouteComponentProps
val Home: ComponentClass<HomeProps> = HomeRComponent::class.react

一方、Route で指定しない場合は withRouter を使用して ComponentClass<P> を得ます。

val Home: ComponentClass<HomeProps> = withRouter(HomeRComponent::class)

@media の定義

メディアクエリは media を使用することで実現できます。

media("(max-width: 40rem)") {
}

ただ、この文字列をいたるところに書くとメンテナンス面で問題があります。このとき、メディアクエリを文字列として管理する方法もありますが、 (CssBuilder, RuleSet) → Rule を定義する方法もあります。例えば、 LayoutmediaMedium と定義すると、 css の中で Layout.mediaMedium(this) { } と使用できます。

object Layout {
    val mediaMedium: (CssBuilder, RuleSet) -> Rule = { cssBuilder, block ->
        cssBuilder.media("(max-width: 40rem)", block)
    }
}
css {
    Layout.mediaMedium(this) {
        flexDirection = FlexDirection.column
    }
}

References