Lightweight scalajs react solution.
Ported react version: 16
- Simple and straightforward style to build react component.
- Use diode instead of redux to manage state.
- Write your DOM tests side by side with scala-jest.
Dependencies:
val sriVersion = "0.3.0"
libraryDependencies ++= Seq(
"com.github.cuzfrog" %%% "simple-sri" % sriVersion,
"com.github.cuzfrog" %%% "simple-sri-diode" % sriVersion, //Diode connector
"com.github.cuzfrog" %%% "simple-sri-test-utils" % sriVersion % Test
)
import sri.react._
import sri.web.vdom.tagsPrefix_<^._
class BasicInput extends Component[BasicInput.Props, BasicInput.State] {
override def getInitialState = BasicInput.State("")
override def render(): ReactRenders = {
<.input(
^.value := state.value,
^.onChange := callback
)
}
private val callback = (event: ReactEventI) => {
val value = event.target.value
setState(s => s.copy(value = value))
println(value)
}
}
object BasicInput {
def apply(props: Props = Props()): ReactElement = CreateElement[BasicInput](props)
case class State(value: String)
case class Props()
}
You could use ComponentP
, ComponentS
to build component that only has Props or State.
Define actions and models:
import diode.Action
case class FilterChange(v: String) extends Action
case class RootModel(filterModel: FilterModel)
case class FilterModel(filterValue: String, filteredElements: Seq[String])
Define diode circuit:
object AppCircuit extends Circuit[RootModel] with ReactConnector[RootModel] {...}
Connect to component:
class FilterInput extends ComponentP[FilterInput.Props] {...}
object FilterInput {
case class Props(value: String, onChange: ReactEventI => Unit)
def apply(): ReactElement = {
AppCircuit.connect(_.filterModel) { proxy =>
def value: String = proxy().filterValue
val onChange: ReactEventI => Unit = (event: ReactEventI) => {
val v = event.target.value
println(s"filter input event! $v | $value")
event.defaultPrevented
proxy.dispatch(FilterChange(v))
}
CreateElement[FilterInput](Props(value, onChange))
}
}
}
You can find examples in tests
sub-project.
A scala class wrapped in a PrototypeComponent
, delegating functionalities to each other.
Thus js native methods have been isolated from the client.
Component can be abstract and have parameters, cause they are common classes:
abstract class AbstractComponent[P,A](args:A) extends ComponentP[P]{...}
But concrete component that is to be instantiated to react element cannot have arguments.
Factory CreateElement
provides ways to create react element.
Clients do not need to manage instances.
See examples in project tests
.
Live example: run sbt tests/fastOptJS
, then npm start
,
a FilterList
could be accessed on localhost:8080
This project derives from scalajs-react-interface by @chandu0101.
Author: Cause Chung (cuzfrog@139.com)
License: Apache License Version 2.0