Skip to content

Commit

Permalink
Typesafe createElement and cloneElement (#605)
Browse files Browse the repository at this point in the history
* Safe constructor for `ReactNode` based on `String`

* Update ReactNode.kt

* warning is suppressed

* Typesafe `childList`

* Fixes after review

* Typesafe `createElement` and `cloneElement`

* Strange unsafe `cloneElement` declarations
  • Loading branch information
sgrishchenko authored Aug 9, 2021
1 parent 23a6c9e commit 1e0015e
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 12 deletions.
8 changes: 4 additions & 4 deletions kotlin-react/src/main/kotlin/react/RBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface RBuilder {
fun <P : Props> child(
type: ElementType<P>,
props: P,
children: List<Any>,
children: List<ReactNode>,
) {
child(createElement(type, props, *children.toTypedArray()))
}
Expand Down Expand Up @@ -72,7 +72,7 @@ interface RBuilder {
)
fun <P : Props> ComponentClass<P>.node(
props: P,
children: List<Any> = emptyList(),
children: List<ReactNode> = emptyList(),
) {
child(this, clone(props), children)
}
Expand All @@ -91,7 +91,7 @@ interface RBuilder {
fun <P : Props> node(
klazz: KClass<out Component<P, *>>,
props: P,
children: List<Any> = emptyList(),
children: List<ReactNode> = emptyList(),
) {
child(klazz.react, props, children)
}
Expand Down Expand Up @@ -174,7 +174,7 @@ inline fun <P : Props, reified C : Component<P, *>> RBuilder.child(
)
inline fun <P : Props, reified C : Component<P, *>> RBuilder.node(
props: P,
children: List<Any> = emptyList(),
children: List<ReactNode> = emptyList(),
) {
child(C::class.react, props, children)
}
Expand Down
6 changes: 5 additions & 1 deletion kotlin-react/src/main/kotlin/react/React.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ fun Children.forEachElement(children: Any?, handler: (ReactElement) -> Unit) =

inline fun <P : Props> cloneElement(
element: ReactElement,
vararg child: Any?,
vararg child: ReactNode?,
props: P.() -> Unit,
): ReactElement = cloneElement(element, jsObject(props), *child)

@Deprecated(
message = "Unsafe API",
replaceWith = ReplaceWith("cloneElement(element, props, child)")
)
fun clone(element: dynamic, props: dynamic, child: Any? = null): ReactElement =
cloneElement(element, props, *Children.toArray(child))

Expand Down
9 changes: 5 additions & 4 deletions kotlin-react/src/main/kotlin/react/ReactElement.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,26 @@ external interface ReactElement : ReactNode {
external fun <P : Props> createElement(
type: String,
props: P = definedExternally,
vararg child: Any?,
vararg child: ReactNode?,
): ReactElement

external fun <P : Props> createElement(
type: ElementType<P>,
props: P = definedExternally,
vararg child: Any?,
vararg child: ReactNode?,
): ReactElement

external fun <P : Props> cloneElement(
element: ReactElement,
props: P = definedExternally,
vararg child: Any?,
vararg child: ReactNode?,
): ReactElement

@Deprecated(message = "Unsafe API")
external fun cloneElement(
element: dynamic,
props: dynamic = definedExternally,
vararg child: Any?,
vararg child: ReactNode?,
): ReactElement

external fun isValidElement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ object Styled {
customStyled(type)
}

fun createElement(type: Any, css: CssBuilder, props: WithClassName, children: List<Any>): ReactElement {
fun createElement(type: Any, css: CssBuilder, props: WithClassName, children: List<ReactNode>): ReactElement {
val wrappedType = wrap(type)
val styledProps = props.unsafeCast<StyledProps>()
styledProps.css = css
Expand Down
4 changes: 2 additions & 2 deletions kotlin-styled/src/main/kotlin/styled/StyledComponents.kt
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ object Styled {
return styledProps.unsafeCast<P>()
}

fun createElement(type: String, css: CssBuilder, props: WithClassName, children: List<Any>): ReactElement {
fun createElement(type: String, css: CssBuilder, props: WithClassName, children: List<ReactNode>): ReactElement {
val wrappedType = wrap(type)
val styledProps = buildStyledProps(css, props)
return createElement(wrappedType, styledProps, *children.toTypedArray())
Expand All @@ -232,7 +232,7 @@ object Styled {
type: ComponentType<P>,
css: CssBuilder,
props: P,
children: List<Any>,
children: List<ReactNode>,
): ReactElement {
val wrappedType = wrap(type)
val styledProps = buildStyledProps(css, props)
Expand Down

0 comments on commit 1e0015e

Please sign in to comment.