Как импортировать модуль узла в React-Kotlin?

Я создал приложение с помощью команды create-реагировать-kotlin-app, и он прекрасно загружается в Chrome. Я добавил пакет React Material UI через NPM, и это было успешно. Теперь, как мне использовать модуль Material UI в моем компоненте?

Обычно с JavaScript это просто import Button from '@material-ui/core/Button' в верхней части файла компонента, но Kotlin это не нравится.

Как мне перевести эту строку на Kotlin? Я не использую Gradle.

2 ответа

Я боролся с этой проблемой уже несколько дней. Я придумал следующее решение. Сначала мы увидим несколько способов объявления внешних модулей, затем я покажу, как их использовать.

Рассмотрим следующий код JavaScript

import Button from '@material-ui/core/Button' // this means button is exported as default

Это будет импортировано в kotlin следующими способами

Button.kt

@file:JsModule('@material-ui/core/Button')
@file:JsNonModule

package com.mypckage.mykillerapp

import react.Component
import react.RProps
import react.RState
import react.ReactElement

// way 1
@JsName("default") // because it was exported as default
external val Button : RClass<RProps>

// way 2
@JsName("default")
external class Button : Component<RProps,RState> {
    override fun render(): ReactElement?
}

Но опять же, если оператор, предназначенный для kotlin, должен соответствовать приведенному ниже оператору импорта javascript,

import { Button } from "material-ui" // not exported as default

Мы используем следующий подход: Button.kt

@file:JsModule('@material-ui/core/Button')
@file:JsNonModule

package com.mypckage.mykillerapp

import react.Component
import react.RProps
import react.RState
import react.ReactElement

// way 1
@JsName("Button") // because it was exported as default
external val Button : RClass<RProps>

// way 2
@JsName("Button")
external class Button : Component<RProps,RState> {
    override fun render(): ReactElement?
}

Как только вы заявили о том, как использовать ваши компоненты, вы можете просто использовать их следующим образом:

//way 1:

fun RBuilder.render() {
    div {
        Button {
            attrs.asDynamic.className="submit-button"
            +"Submit"
        }
    }
}

//way 2:
fun RBuilder.render() {
    div {
        child(Button::class) {
            attrs.asDynamic.className="submit-button"
            +"Submit"
        }
    }
}

отличный. Вы импортировали свой компонент. Но до тех пор вы не полагаетесь на безопасность типа kotlin и даже на завершение кода, чтобы достичь этого, вы должны пойти на дополнительную длину

как показано ниже

external interface ButtonProps: RProps {
    var className : String
    var onClick: (Event?)->Unit
    var color: String
    // . . .
    var href: String
}

затем идти вперед и объявить вашу кнопку как

@JsModule("@material-ui/core/Button")
@JsNonModule
@JsName("default") // because it was exported as default
external val Button : RClass<ButtonProps>

и теперь вы можете использовать его с типом безопасности и завершения кода, как показано ниже

fun RBuilder.render() {
    div {
        Button {
            attrs {
                className = "submit-button"
                onClick = {
                    window.alert("Vois La")   
                }
            }
            +"Submit"
        }
    }
}

Надеюсь это поможет. Удачного кодирования

Способ импорта зависимостей Kotlin близок к стандартному импорту JS:

import React from 'react';

export function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Основано на создании простого компонента React с Kotlin.

package hello

import react.*
import react.dom.*

fun RBuilder.hello(name: String) {
    h1 {
        +"Hello, $name"
    }
}

Обычно (поскольку Kotlin основан на Java), он использует инструмент Gradle для обработки зависимостей:

// part of build.gradle
kotlinFrontend {
    // ...

    npm {
        // ...

        dependency("react")
        dependency("react-dom")
        dependency("react-router")
        dependency("react-markdown")

        devDependency("css-loader")
        devDependency("babel-core")
        // ...
    }

И ссылки, как указано выше:

HomeView.kt:

// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/HomeView.kt

import kotlinx.html.*
import org.jetbrains.demo.thinkter.model.*
import react.*
import react.dom.*
import kotlinx.coroutines.experimental.launch

ReactMarkdown.kt:

// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/ReactMarkdown.kt

package org.jetbrains.demo.thinkter

import react.*

private val ReactMarkdown: dynamic = runtime.wrappers.require("react-markdown")

Основано на: https://github.com/Kotlin/kotlin-fullstack-sample


В create-react-kotlin-app дополнительно столкнулся с возможностью импорта с @JsModule() аннотации, а управление зависимостями обрабатывается стандартным способом через package.json:

// src/logo/Logo.kt (outcome of creating new app)
package logo

import react.*
import react.dom.*
import kotlinext.js.*
import kotlinx.html.style

@JsModule("src/logo/react.svg")
external val reactLogo: dynamic
@JsModule("src/logo/kotlin.svg")
external val kotlinLogo: dynamic

И может также успешно использоваться для импорта библиотек JS.

Другой способ будет использовать kotlinext.js.*:

// index/index.kt

import kotlinext.js.*

fun main(args: Array<String>) {
    requireAll(require.context("src", true, js("/\\.css$/")))

    // ...
}

Что также обеспечивает require(module: String) функция.

Другие вопросы по тегам