Scala-js-react provides nice statically typed interface to Facebook's React.
For detailed sbt configuration please refer to scala.js documentation.
build.sbt
enablePlugins(ScalaJSPlugin)
scalaVersion := "2.11.5"
libraryDependencies ++= Seq(
  "com.xored.scalajs" %%% "scalajs-react" % "0.3.3",
  compilerPlugin("org.scalamacros" % "paradise" % "2.0.1" cross CrossVersion.full)
)project/plugins.sbt
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.0")project/build.properties
sbt.version=0.13.7
scala-js-react aims to support all Facebook React features.
While Facebook React uses JSX, scala-js-react offers scalax support.
Basically scalax allows to use Scala XML literals to build React DOM.
React DOM allows to put objects into attribute values, while scala.xml.UnprefixedAttribute constructor takes Seq[Node] or String.
So we have to transform methods before it typechecks. That is why scalax scalax uses macro annotations and requires macro paradise compiler plugin.
object HelloMessage extends TypedReactSpec {
  case class State()
  case class Props(name: String)
  def getInitialState(self: This) = State()
  @scalax
  def render(self: This) = {
    <div>Hello {self.props.name}</div>
  }
}
React.renderComponent(
  HelloMessage(HelloMessage.Props(name = "John")),
  mountNode
)A component can maintain internal state.
object Timer extends TypedReactSpec with TypedEventListeners {
  case class Props()
  case class State(secondsElapsed: Int, interval: Option[Int])
  def getInitialState(self: This) = State(secondsElapsed = 0, interval = None)
  implicit class Closure(self: This) {
    import self._
    val tick = () => {
      setState(state.copy(secondsElapsed = state.secondsElapsed + 1))
    }
  }
  override def componentDidMount(self: This) = {
    val interval = window.setInterval(self.tick, 1000)
    self.setState(self.state.copy(interval = Some(interval)))
  }
  override def componentWillUnmount(self: This) = {
    self.state.interval.foreach(window.clearInterval)
  }
  @scalax
  def render(self: This) = {
    <div>Seconds Elapsed: {self.state.secondsElapsed}</div>
  }
}object Say extends TypedReactSpec with TypedEventListeners {
  case class Props()
  case class State(text: String)
  implicit class Closure(self: This) {
    import self._
    val onChange = input.onChange(e => {
      setState(state.copy(text = e.target.value))
    })
    val onClick = button.onClick(e => {
      alert(state.text)
    })
  }
  def getInitialState(self: This) = State(text = "")
  @scalax
  def render(self: This) = {
    <div>
      <input type="text" value={self.state.text} onChange={self.onChange}></input>
      <button type="text" onClick={self.onClick}>Say</button>
    </div>
  }
}$ sbt "project scalajs-react-examples" fastOptJS
$ open scalajs-react-examples/index.html
Copyright © 2014 Xored Software, Inc.
Licensed under the Apache License, Version 2.0.