From 36aad5f7df4f574b319a4c200391a956f0dc616c Mon Sep 17 00:00:00 2001 From: Shadaj Laddad Date: Sat, 30 May 2020 16:46:20 -0700 Subject: [PATCH] Allow exporting external components to `ReactComponentClass` instances Fixes #336 --- CHANGELOG.md | 5 ++++- .../scala/slinky/core/ReactComponentClass.scala | 11 +++++++++++ .../slinky/core/ExportedComponentTest.scala | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2daf9104..df858816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,13 @@ ## vNEXT ### Highlights :tada: -+ Updated scalajs-dom to 1.0.0 [PR #362](https://github.com/shadaj/slinky/pull/362) ++ Updated `scalajs-dom` to 1.0.0 [PR #362](https://github.com/shadaj/slinky/pull/362) + Add facades for the `React.Profiler` component [PR #372](https://github.com/shadaj/slinky/pull/372) + Add facades for the `act` funcion in `react-test-renderer` [PR #376](https://github.com/shadaj/slinky/pull/376) +### Bug Fixes :bug: ++ Allow exporting external component definitions as instances of `ReactComponentClass` [PR #377](https://github.com/shadaj/slinky/pull/377) + ### Breaking Changes :warning: + Due to the update of scalajs-dom to 1.0.0 a support for `dd` and `dt` tags has been dropped. diff --git a/core/src/main/scala/slinky/core/ReactComponentClass.scala b/core/src/main/scala/slinky/core/ReactComponentClass.scala index 4d39703a..b854b1da 100644 --- a/core/src/main/scala/slinky/core/ReactComponentClass.scala +++ b/core/src/main/scala/slinky/core/ReactComponentClass.scala @@ -17,6 +17,17 @@ object ReactComponentClass { .componentConstructor(propsReader, wrapper.hot_stateWriter, wrapper.hot_stateReader, ctag) .asInstanceOf[ReactComponentClass[wrapper.Props]] + implicit def externalToClass( + external: ExternalComponentWithAttributesWithRefType[_, _] + ): ReactComponentClass[external.Props] = + external.component + .asInstanceOf[ReactComponentClass[external.Props]] + + implicit def externalNoPropsToClass( + external: ExternalComponentNoPropsWithAttributesWithRefType[_, _] + ): ReactComponentClass[Unit] = + external.component.asInstanceOf[ReactComponentClass[Unit]] + implicit def functionalComponentToClass[P]( component: FunctionalComponent[P] )(implicit propsReader: Reader[P]): ReactComponentClass[P] = diff --git a/tests/src/test/scala/slinky/core/ExportedComponentTest.scala b/tests/src/test/scala/slinky/core/ExportedComponentTest.scala index 6cf84914..6b9ad0d1 100644 --- a/tests/src/test/scala/slinky/core/ExportedComponentTest.scala +++ b/tests/src/test/scala/slinky/core/ExportedComponentTest.scala @@ -31,6 +31,11 @@ object TestExportedComponentStateless extends StatelessComponentWrapper { } } +object TestExportedExternalComponent extends ExternalComponentNoProps { + case class Props(children: Seq[ReactElement]) + val component = "div" +} + class ExportedComponentTest extends AnyFunSuite { test("Can construct an instance of an exported component with JS-provided props") { val container = document.createElement("div") @@ -72,4 +77,16 @@ class ExportedComponentTest extends AnyFunSuite { assert(container.innerHTML == "lol") } + + test("Can construct an instance of an exported external component with JS-provided props") { + val container = document.createElement("div") + ReactDOM.render(React.createElement( + TestExportedExternalComponent: ReactComponentClass[_], + js.Dictionary( + "children" -> js.Array("hello") + ) + ), container) + + assert(container.innerHTML == "
hello
") + } }