tacos_tacos_tacos tacos_tacos_tacos - 7 months ago 41
Javascript Question

Wrapping/facading a ScalaJS react js component (react-sticky) in the most encapsulating manner possible

I have seen several methods of making a facade or wrapping Javascript components in

scala.js
, including doing so for
react.js Component
s. They seem to vary in the degree they encapsulate or hide the functionality provided by the component itself, I suppose based on their needs (maybe they only need to call one method).

In my case, I need to use a component called
react-sticky
and I am first trying to determine how to proceed with making a facade for one of its just two component classes,
StickyContainer
, code provided here.


My questions are as follows:


  1. How do I deal with
    static
    Javascript methods in
    scala
    ? Do I even need to care about this, or can I be agnostic about it?

  2. What is the minimum amount of "facade" I need to make to just include the
    component
    without any
    Props
    in another
    component
    's
    render()
    ?

  3. What is fundamentally different about wrapping or facading a
    reactjs
    component as opposed to any other
    js
    native class?



Finally, which of the following strategies would be most appropriate?

@js.native
trait StickyContainer extends js.Object { ... }
object StickyContainer extends StickyContainer {}


or

case class StickyContainer(offset: js.UndefOr[Double],...) {
def apply() = { React.createElement(ReactUniversal.Image, JSMacro[StickyContainer](this), children: _*)
}

Answer

How do I deal with static Javascript methods in scala? Do I even need to care about this, or can I be agnostic about it?

You don't need worry about underlying implementations of react components,when you want to wrap it. But in general if you want specify static fields for a class

 @ScalaJSDefined
 class MyComponent extends ReactComponent {
  ...
}

val ctor = js.constructorOf[MyComponent]

ctor.childContextTypes = js.Dictionary("contextfield" -> React.PropTypes.`object`.isRequired)

If you're wondering about out of box static fields support in scala.js .. https://github.com/scala-js/scala-js/issues/1902

What is the minimum amount of "facade" I need to make to just include the component without any Props in another component's render()?

global.ReactSticky = require('react-sticky') // load js lib

@js.native
object ReactSticky extends js.Object {
  val StickyContainer : js.Dynamic = js.native
  val Sticky : js.Dynamic = js.native
}

//Using JSMacro
case class StickyContainer(fields ..) {
  def apply(children : ReactNode*) = {
     val props  = JSMacro[StickyContainer](this)
     React.createElement(ReactSticky.StickyContainer,props,children :_*) 
   }
}

//Using FunctionMacro
def StickyContainer(fields ..)(children : ReactNode*) : ReactElement = {
     val props  = FunctionMacro()
     React.createElement(ReactSticky.StickyContainer,props,children :_*) 
   }
}

What is fundamentally different about wrapping or facading a reactjs component as opposed to any other js native class?

If you see object ReactSticky extends js.Object ... there is no difference in writing facade. but in react world you need ReactElements thats where you need extra wrapper for - React.createElement(classCtor,props,children) call ..

Comments