Kotlin/JS wrapper for React, React Router and react-helmet-async.
- Similar to kotlin-react.
- Nicer and consistent API. Easier to use.
- Not multiplatform. Optimized for Kotlin/JS instead.
- Lower size and performance overhead.
- More type safety, esp. around hooks.
- With new Concurrent Mode in mind, thus depending on experimental React releases.
- Props allow
class
instead of justexternal interface
. - Updates of local properties delegated with
by useState(…)
are reflected immediately. - Support for coroutines with
CoroutineScope(…) { … }
,useCoroutineScope()
anduseFlow(…)
. @DslMarker
colors.- Experimental and IR compiler only. Relies on compiler-internal behavior until KT-10468 is solved.
- Contributions welcome 😃
- Kotlin/JS-optimized CSS library with nice API in the works.
- Components created with
react.component()
are memoized by default unless they have children (react.componentWithChildren()
). - Memoization of components created with
react.component()
or added byRComponent.memo()
useequals()
to compare Props. You must ensure that your props implementequals()
in order to benefit from memoization. - Hook dependencies use
equals()
instead of===
. They don't need to be anArray
nor is the same amount of dependencies needed for each render. - Router routes are
exact
,strict
andsensitive
by default.
build.gradle.kts
:
dependencies { implementation("io.fluidsonic.react:fluid-react-dom:0.13.0") // basis module implementation("io.fluidsonic.react:fluid-react-coroutines:0.13.0") // optional coroutine support implementation("io.fluidsonic.react:fluid-react-helmet:0.13.0") // optional dynamic metadata (react-helmet-async) implementation("io.fluidsonic.react:fluid-react-router-dom:0.13.0") // optional routing (react-router) }
import io.fluidsonic.react.* import kotlinx.browser.* fun main() { val body = checkNotNull(document.body) val container = document.createElement("div").also(body::appendChild) react.createRoot(container).render { +"Hello world" EmojiContainer(EmojiContainerProps("😍")) { strong { +"cool" } } } } val EmojiContainer by react.componentWithChildren { props: EmojiContainerProps, children -> var count by useState(3) useEffect(count) { val timerId = window.setTimeout({ count += 1 }, 2000) cleanup { window.clearTimeout(timerId) } } h1 { +"Your emoji, $count times 🎉" } button { attrs.onClick = { count += 1 } +"Add one" } ol { repeat(count) { li { +props.emoji +" " children() } } } } class EmojiContainerProps(val emoji: String)
Also check out the playground and run it from IntelliJ IDEA.