Is it possible to add a function as the children p...
# react
b
Is it possible to add a function as the children property of a component? This seems to be a common react JS thing that I can't figure out in Kotlin. For example, how would one implement this lib? react-virtualized-auto-sizer
t
Copy code
external interface MyProps {
    var children: (String) -> ReactNode
}
?
b
Yeah, I'm doing something like this but can't seem to get it working
Copy code
@JsModule("react-virtualized-auto-sizer")
@JsNonModule
external val module: dynamic

val autoSizer: RClass<AutoSizerProps> = module.default

external interface AutoSizerProps : RProps {
    var children: (dynamic) -> ReactElement
}
And then something like this. I don't get any crashes, but the inner component doesn't render.
Copy code
autoSizer {
    attrs.children = { size -> myComponent { attrs.height = size.height } }
}
t
b
Yeah, this setup gets me the same autoSizer as before:
Copy code
@file:JsModule("react-virtualized-auto-sizer")
@file:JsNonModule

import react.*

@JsName("default")
external val autoSizer: RClass<AutoSizerProps>

external interface AutoSizerProps : RProps {
    var children: (dynamic) -> ReactElement
}
What do you mean by isolated builder?
t
Copy code
myComponent { 
   attrs.height = size.height 
}
myComponent
called on builder provided by
autoSizer
As result - you have
children: ReactNode[]
instead of
children: (T) -> ReactElement
Copy code
myComponent { 
   attrs.height = size.height 
}
Move this code to separate method to see a problem
b
Ok, so what is the work around? Use
buildElement
?
Also, if put a print statement in
attrs.children = { size -> ... }
then it never gets printed. So I'm not sure why that is either.
t
Ok, so what is the work around? Use 
buildElement
 ?
Or
createElement
for simple cases
b
Hmmm, ok. Yeah, neither seems to work. 😕
s
here example of declaration of component with children function https://github.com/JetBrains/kotlin-wrappers/pull/575 may be it is also will help ``````
t
Example contains initial problem 🙂 We will update it
b
Is that
RBuilder.() -> Unit
pattern possible with external components?
s
No, but you can try to wrap API of react-virtualized-auto-sizer to something like this In react wrappers there is
Context.Consumer
that actually solve similar problems
b
Ok. Interesting. Seems a bit over my head for now. Though I might try it out sometime in the future
t
Strict and safe contract
Copy code
@JsName("default")
external val autoSizer: FC<AutoSizerProps>

external interface AutoSizerProps : RProps {
    var children: FC<AutoSizerChildProps>
}

external interface AutoSizerChildProps : RProps {
    val width: Double
    val height: Double
    // ...
}
👍 1
s
I will try to write some example but I cant garantee that it will work without some corrections
Copy code
// file AutoSizer.kt
@JsModule("react-virtualized-auto-sizer")
@JsNonModule
external val module: dynamic

val autoSizer: RClass<AutoSizerProps> = module.default

external interface AutoSizerProps : RProps {
    var children: (dynamic) -> ReactElement
}

// file AutoSizer.ext.kt
var AutoSizerProps.children: RBuilder.(dynamic) -> Unit 
  get() = this.children
  set(handler) {
       child(this, jsObject {
            this.children = { value ->
                buildElements { handler(value) }
            }
        }) {}
   }

// or you can try to declare children as Function Componet
var AutoSizerProps.children: FunctionComponent<dynamic>
  get() = this.children
  set(component) {
       child(this, jsObject {
            this.children = component
        }) {}
   }
also if you dont watn to support get section you can use this pattern
Copy code
var RProps.key: Key
    @Deprecated(message = "Write-only property", level = DeprecationLevel.HIDDEN)
    get() = error("")
    set(value) {
        asDynamic().key = value
    }
it is write-only property example
b
@turansky How do you run that example? I tried something like this but it didn't render as before.
Copy code
child(autoSizer) {
    attrs.children = myComponent
}
t
child
- redundant in your example
b
If the type is
FC<AutoSizerProps>
then don't you need it?
I'm assuming you have
import react.FunctionalComponent as FC
t
import react.FC
Available in latest wrappers
b
Oh. I'm still on
kotlin-react:17.0.1-pre.146-kotlin-1.4.30
So FC is different than FunctionalComponent?
s
Nope, it is type aliase
b
Ok
I guess I'm still just lost on how to get this working. Are there any example of this for an external JS library?
t
You have quite outdated wrappers, which possibly contains some blockers/bugs
We have examples in wrappers for non-children properties
b
I mean, it the version from the tutorial from a few months ago. 😉 But yeah, I'll have to update one of these days.
t
In any case if
children
as function doesn’t work as expected it will be fixed in
pre.225+
version
b
I think I'm going to just write my on
.js
wrapper to get around all of this. Thanks anyways!
😞 1
t