0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

kotlin-react-routerを6.3->6.7にする時にRouteで躓いた

Last updated at Posted at 2023-07-23

要約

kotlin-react-routerを6.3.0-pre491から6.7.0-pre492にする段階でRoute関数のラムダ式引数内でpathelementが使えなくなるが、this as PathRoutePropsでキャストすれば回避できる。

さらに先のバージョン(6.17.0-pre635)ではこの回避策も無効になる(続編参照)。

環境

  • Ubuntu 20.04LTS
  • IntelliJ IDEA 2023.1.4 (Community Edition)
  • Kotlin/JS 1.8.20(IRコンパイラ)
  • Kotlin Wrappers 1.0.0-pre.598
  • kotlin-react-router-dom 6.14.1-pre.598
  • gradle 8.1.1

動機

2023年7月現在Kotlin Wrappersに、"React wrappers in particular heavily relied on specific characteristics of the default backend, which might make your current code incompatible with the new IR backend."と書かれているので、LEGACYコンパイラのままにしてきた。しかし、Kotlin 1.9がリリースされLEGACYコンパイラが廃止される流れになっているので、コンパイラの切り替えとライブラリの更新を一気に行おうと思った。

現象

Kotlin Wrappersを1.0.0-pre.348から1.0.0-pre.598に更新し、build.gradle.ktsでコンパイラの指定をLEGACYからIRに変更した。これに合わせてkotlin-react-router-domのバージョンも6.3.0-pre.348から6.14.1-pre.598に変更した。

ソースコードの変更はimport react.dom.htmlimport web.htmlに変更するといった対応で済むものが多かったが、React Routerに関しては

import react.FC
import react.Props
import react.router.Route
import react.router.Routes
import react.router.dom.BrowserRouter

val Main = FC<Props> {
    BrowserRouter {
        Routes {
            Route {
                path = "sample.html"
                element = createElement(Sample)
            }
        }
    }
}

のように書いて問題なく動作していたのが、pathelementの所でエラーが出るようになった。

調査

Kotlin Wrappersのソースコード

pathelementreact.router.RouteProps由来とのことで、該当部分のソースを参照すると、

sealed external interface RouteProps : react.Props /* export type RouteProps = PathRouteProps | LayoutRouteProps | IndexRouteProps; */

となっている。これが、ライブラリ更新前だと、

external interface RouteProps : react.PropsWithChildren {
    var caseSensitive: Boolean?
    override var children: react.ReactNode?
    var element: react.ReactNode?
    var index: Boolean?
    var path: String?
}

となっており、更新に際して属性の指定が消されてしまっている。

React Routerのソースコード

これだけだと解決策が浮かばないのでReact Routerのソースを探ってみた。

export type RouteProps = PathRouteProps | LayoutRouteProps | IndexRouteProps;

はKotlin側のソースでコメントアウトされていた通り。そしてPathRouteProps, LayoutRouteProps, IndexRoutePropsはそれぞれ、

  • PathRouteProps: pathelementがある。
  • LayoutRouteProps: PathRoutePropsと同等。
  • IndexRouteProps: PathRoutePropsindexをtrueにしたもの。

といった状態であった。ちなみにPathRoutePropsに対応してPathRouteがある訳ではなく、あるのはRouteだけの模様。

推定される原因と解決法

RoutePropsの属性情報が消された上に、PathRouteProps, LayoutRouteProps, IndexRoutePropsのどれであるか特定する方法がないので、pathelementにアクセスできない。

逆に言うとPathRouteProps, LayoutRouteProps, IndexRoutePropsのどれであるか特定できればpathelementにアクセスできるようになりそう。

解決

Routeの型引数にPathRoutePropsを指定して解決を図ろうとしたが、うまく行かなかった。以下のようにthis as PathRoutePropsでキャストを強制したらこれまで通り動作するようになった。

import react.FC
import react.Props
import react.router.PathRouteProps
import react.router.Route
import react.router.Routes
import react.router.dom.BrowserRouter

@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE")
val Main = FC<Props> {
    BrowserRouter {
        Routes {
            Route {
                this as PathRouteProps
                path = "sample.html"
                element = createElement(Sample)
            }
        }
    }
}

IndexRouteProps

前述の通りreact.router.IndexRoutePropsというものがあるが、index = trueRouteでこれにキャストしてもうまく行かなかった。
代わりに上記PathRoutePropsにキャストした後、pathを設定せずにindex = trueとしたら問題なかった。

考察

ライブラリを更新しないという選択も

ちなみに、kotlin-react-router-domのバージョンを6.3.0に据え置いたままコンパイラをIRにして他のReact関連のラッパーを更新しても、自分の使用している範囲では問題がなかった。

いちいちキャストが必要というのは明らかに使いづらいので、もしかしたら改善されるかもしれない。という希望的観測のもと、もうしばらく放置しておくというのは必ずしも悪い考えではないと思う。

発生時期など

GitHubの履歴によると、2023年2月上旬の6.3.0-pre.491から6.7.0-pre.492への変更でフォルダ構成と共に色々変わってこうなったようだ。

kotlin-react-router-domの以前のreadme.mdにはサンプルコードが載っていたのだが、上記更新の際に消えてしまっている。発生する問題の説明がないのも頂けないが、せめて動作するサンプルコードくらい載せてくれればここまで悩まずに済んだ。

自動生成のコードのようなので、開発側も自分自身で使っていないのかもしれない。

改訂履歴(表現の修正などは除く)

  • 2023/5/14: 挫折してしばらく放置
  • 2023/7/23: ライブラリの更新に成功
  • 2023/7/24: 初版作成
  • 2024/8/4: 続編へリンク
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?