Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import node module in React-Kotlin?

I created an app using the create-react-kotlin-app command and it loads in Chrome fine. I added the React Material UI package via NPM and that was successful. Now how do I use the Material UI module in my component?

Normally with JavaScript, it's a simple import Button from '@material-ui/core/Button' at the top of the component's file, but Kotlin doesn't like that.

How do I translate that line to Kotlin? I am not using Gradle.

like image 236
Alex Avatar asked Jul 19 '18 21:07

Alex


People also ask

How do I import a node module into react?

Load the NPM Module Using the GitHub Repository Along with the CLI command, add the required GitHub repository URL of the module that you want to install. A folder gets created inside the directory node_modules by providing the GitHub URL along with the install command. And the package gets mentioned in package. json .

Can I use Nodejs library in react?

Both Nodejs and React are javascript languages that can be executed both client and server-side. Developers can execute the Reactjs code directly in the Nodejs environment. The React DOM has components specifically designed to work with Nodejs that reduce lines of code, making server-side rendering comparatively easy.

Can you use kotlin With react?

The Kotlin wrappers for React come with a domain-specific language (DSL) that makes it possible to write HTML in pure Kotlin code. In this way, it's similar to JSX from JavaScript. However, with this markup being Kotlin, you get all the benefits of a statically typed language, such as autocomplete or type checking.

Can kotlin compile to JavaScript?

Kotlin for JavaScript Kotlin/JS provides the ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies to JavaScript. The current implementation of Kotlin/JS targets ES5.


1 Answers

I have been struggling with this problem for days now. I came up with the following solution. First we will see multiple ways to declare external modules, then I will show how to use them .

Consider the following javascript code

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

This will be imported in kotlin in the following ways

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

@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?
}

But again, if the statement intend for kotlin has to match the javascript import statement bellow,

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

We use the following approach: Button.kt

@file:JsModule("material-ui")
@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?
}

once you have declared on how to use your components, you can just use them as follows:

//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"
        }
    }
}

great. you have imported your component. But until then your are not relying on kotlin type safety and even code completion, to achieve that, you have to go to extra length

as shown bellow

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

then go ahead and declare your button as

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

and you can now use it with type safety and code completion as shown bellow

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

Hope this helps. Happy coding

EDIT: There is a community wrapper for material-ui components here

HINT: Use way 1, as you can see, it is less verbose

like image 51
andylamax Avatar answered Sep 20 '22 03:09

andylamax