You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Alexey Tsvetkov
d23806a3f4
|
3 years ago | |
---|---|---|
.. | ||
gradle/wrapper | 3 years ago | |
src/jsMain | ||
webpack.config.d | ||
.gitignore | 3 years ago | |
README.MD | ||
build.gradle.kts | ||
gradle.properties | ||
gradlew | ||
gradlew.bat | ||
settings.gradle.kts |
README.MD
How to use HTML based @Composable functions in JS?
Useful links:
- @Composable functions can't be invoked from JS directly (because every @Composable function has implicit parameters added by compiler plugin)
- We can wrap @Composable functions into some usual function (with @JsExport) which can be invoked in JS as is.
- Every call to a "wrapping" function will create a composition (part of DOM controlled by Compose runtime)
- It's important to
dispose
a composition when it's not needed. - The composition's state can be controlled by creating an arbitrary
Controller
class, which implements and exposes necessary functions for state updates.
Simplified example (see full example in src/jsMain
):
// Composables.kt
@JsExport
abstract class ComposeCounterAppController {
abstract fun setCount(newCount: Int)
abstract fun dispose()
}
@JsExport
fun ComposeCounterApp(rootId: String, onCountChange: (Int) -> Unit = {}): ComposeCounterAppController {
var count: Int by mutableStateOf(0)
val composition = renderComposable(rootElementId = rootId) {
// Counter is a @Composable function
// see full example in src/jsMain
Counter(count) {
count = it
onCountChange(count)
}
}
return object : ComposeCounterAppController() {
override fun setCount(newCount: Int) {
count = newCount
}
override fun dispose() {
composition.dispose()
}
}
}
Then in JS we can use ComposeCounterApp
function:
// see src/jsMain/resources/use_compose.js file for a full example
counterController = MyComposables.ComposeCounterApp('counterByCompose', (newCount) => {
console.log(`Counter was updated. New value = ${newCount}`);
});
The module name was overridden to make it convenient for usage in JS:
// webpack.config.d/configModuleName.js
config.output = config.output || {};
config.output.library = "MyComposables";
Building and using the output
./gradlew jsBrowserProductionWebpack
This will produce the output in build/distributions
.
Then we can use exported functions from web-compose-in-js.js
(the filename is defined by the project/module name).
<script src="web-compose-in-js.js"></script>
<script src="use_compose.js"></script>