chandu0101 / sri

Build truly native cross platform (web,ios,android) apps using scalajs and react, react-native ,This project moved to new organization : https://github.com/scalajs-react-interface/sri#sri, new chat room : https://gitter.im/scalajs-react-interface/sri
Apache License 2.0
634 stars 35 forks source link

Eliminate getTypedConstructor boilerplate #45

Closed nafg closed 7 years ago

nafg commented 8 years ago

First, create a base trait

trait ReactComponentBase {
  type Props
  type State
}

then make ReactComponent extend it and fill in type members to its type arguments.

Then you can have

def typedConstructor[A](implicit ct: ConstructorTag[A]) = ct.constructor.asInstanceOf[ReactTypedConstructor[P, S]]

However I would take it a step further:

class ReactFactory[A, P, S](val ctor: js.Dynamic) {
  def typed = ctor.asInstanceOf[ReactTypedConstructor[P, S]]
  def createElement(props: P): ReactElementU[P, S] = ...
  // all the createElement variants
}
object ReactFactory {
  def apply[A <: ReactComponentBase](implicit ct: ConstructorTag[A]) = new ReactFactory[A, A#Props, A#State](ct.constructor)

Now you can write ReactFactory[MyComponent].createElement(...)

Note: createElement is necessary, we can't just call it apply and use function application syntax, since that would get interpreted as filling the implicit parameter list.

Alternatively, createElement etc. could be modified to something like

def createElement[A <: ReactComponentBase](props: A#Props, ...)(implicit ct: ConstructorTag[A]) = ...

(or take ReactFactory implicitly as a typeclass).

chandu0101 commented 7 years ago

merged code from @nafg fork. thank you @nafg :)