Skip to content

Commit

Permalink
Migrate to react-router v4 (#27)
Browse files Browse the repository at this point in the history
* Correct props

- Create react element via <(ReactClassSpec)(attribute: Any*)(contents: Any*) method
- Specify props via ^.wrapped attribute
- Use props.children to access children
- Use props.router, props.location, etc to access router props

* Fix travis CI

* Use Chrome instead

* Fix travis CI

* Fix travis CI

* Remove children method

It is replaced by props.children

* Create react-router-dom facade

* Drop 2.11 support

It was having issue resolving class for WebBrowser for no obvious reason.

* Update README.md

* Update documentations

Close #26

* Drop Scala 2.11 from travis

* Update README.md

* Remove comments

* Update documents

* Update README.md

* Update Main.scala

* Loosen selenium version

Travis is having issue finding 3.3.1

* Try installing newer chromdriver

* Revert manually downloding chromedriver

* Install google-chrome-stable

* Revert "Install google-chrome-stable"

This reverts commit d1f45c3.

* Install Chrome

* Use chromedriver 2.28

According to https://bugs.chromium.org/p/chromedriver/issues/detail?id=1467, it has the fix for alert hanging.

* Ignore unexpected alert

* Use singleton FirefoxDriver

* Install geckodriver

* Fix gecko download path

* Do not use trusty
  • Loading branch information
shogowada authored Apr 15, 2017
1 parent 9eb8a5d commit fbe1403
Show file tree
Hide file tree
Showing 46 changed files with 788 additions and 1,144 deletions.
10 changes: 7 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
language: scala

scala:
- 2.11.8
- 2.12.1

jdk:
- oraclejdk8

addons:
firefox: "latest"

before_script:
- wget https://github.com/mozilla/geckodriver/releases/download/v0.15.0/geckodriver-v0.15.0-linux64.tar.gz
- mkdir geckodriver
- tar -xzf geckodriver-v0.15.0-linux64.tar.gz -C geckodriver
- export PATH=$PATH:$PWD/geckodriver
- "export DISPLAY=:99"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
- ". $HOME/.nvm/nvm.sh"
- "nvm install node"
- "nvm use node"
- "node --version"
- "npm --version"

script:
- sbt ++$TRAVIS_SCALA_VERSION fastOptJS::webpack
Expand Down
41 changes: 17 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@

[![Build Status](https://travis-ci.org/shogowada/scalajs-reactjs.svg?branch=master)](https://travis-ci.org/shogowada/scalajs-reactjs)

Develop React JS applications with Scala. It is compatible with Scala 2.11, 2.12, and Scala.js 0.6.14+.
Develop React applications with Scala. It is compatible with Scala 2.12 and Scala.js 0.6.14.

Optionally include react-router and react-redux facades, too.

## Quick Look

```scala
import io.github.shogowada.scalajs.reactjs.VirtualDOM._

class HelloWorld extends StatelessReactClassSpec[HelloWorld.Props] {
override def render() = <.div(^.id := "hello-world")(s"Hello, ${props.name}!")
class HelloWorld extends StatelessReactClassSpec[HelloWorld.WrappedProps] {
override def render() = <.div(^.id := "hello-world")(s"Hello, ${props.wrapped.name}!")
}

object HelloWorld {
case class Props(name: String)
case class WrappedProps(name: String)

def apply(props: Props): ReactElement = (new HelloWorld) (props)()
def apply() = new HelloWorld()
}

val mountNode = dom.document.getElementById("mount-node")
ReactDOM.render(HelloWorld(HelloWorld.Props("World")), mountNode)
ReactDOM.render(<(HelloWorld())(^.wrapped := HelloWorld.WrappedProps("World"))(), mountNode)
```

You can also use a pure function to render:
Expand All @@ -29,14 +31,11 @@ You can also use a pure function to render:
import io.github.shogowada.scalajs.reactjs.VirtualDOM._

object HelloWorld {
case class Props(name: String)

def apply(props: Props): ReactElement = <.div(^.id := "hello-world")(s"Hello, ${props.name}!")
def apply(name: String): ReactElement = <.div(^.id := "hello-world")(s"Hello, ${name}!")
}

val mountNode = dom.document.getElementById("mount-node")
ReactDOM.render(HelloWorld(HelloWorld.Props("World")), mountNode)

ReactDOM.render(HelloWorld("World"), mountNode)
```

## How to Use
Expand All @@ -45,22 +44,16 @@ ReactDOM.render(HelloWorld(HelloWorld.Props("World")), mountNode)
2. Depend on the libraries.
```
libraryDependencies ++= Seq(
"io.github.shogowada" %%% "scalajs-reactjs" % "0.7.1", // For react facade
"io.github.shogowada" %%% "scalajs-reactjs-router" % "0.7.1", // Optional. For react-router facade
"io.github.shogowada" %%% "scalajs-reactjs-redux" % "0.7.1" // Optional. For react-redux facade
"io.github.shogowada" %%% "scalajs-reactjs" % "0.8.0", // For react facade
"io.github.shogowada" %%% "scalajs-reactjs-router-dom" % "0.8.0", // Optional. For react-router-dom facade
"io.github.shogowada" %%% "scalajs-reactjs-redux" % "0.8.0" // Optional. For react-redux facade
)
```

## Examples

- [TODO App](./example/todo-app)
- [Routing](./router)
- [Redux](./redux)
- [Basics](./example)
- [TODO App](./example/todo-app/src/main/scala/io/github/shogowada/scalajs/reactjs/example/todoapp/Main.scala)
- [Routing](./example/routing/src/main/scala/io/github/shogowada/scalajs/reactjs/example/routing/Main.scala)
- [Redux](./example/todo-app-redux/src/main/scala/io/github/shogowada/scalajs/reactjs/example/todoappredux)
- [I don't like `<` and `^`. How can I change them?](./example/custom-virtual-dom)
- [All Examples](./example)

## API References

- [react facade](./core)
- [react-router facade](./router)
- [react-redux facade](./redux)
32 changes: 25 additions & 7 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
val CreateReactClassVersion = "^15.5.1"
val ReactVersion = "^15.5.3"
val ReactReduxVersion = "^5.0.3"
val ReactRouterVersion = "^3.0.0"
val ReactRouterVersion = "^4.0.0"
val ReduxVersion = "^3.6.0"
val WebpackVersion = "^2.3.2"

val StaticTagsVersion = "[2.4.0,3.0.0["

crossScalaVersions := Seq("2.11.8", "2.12.1")
val SeleniumVersion = "[3.0.0,4.0.0["
val ScalaTestVersion = "[3.1.0,4.0.0["

crossScalaVersions := Seq("2.12.1")

publishTo := {
val nexus = "https://oss.sonatype.org/"
Expand All @@ -21,7 +24,7 @@ publishArtifact := false
val commonSettings = Seq(
organization := "io.github.shogowada",
name := "scalajs-reactjs",
version := "0.7.2-SNAPSHOT",
version := "0.8.0",
licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT")),
homepage := Some(url("https://github.com/shogowada/scalajs-reactjs")),
scalaVersion := "2.12.1",
Expand Down Expand Up @@ -83,6 +86,20 @@ lazy val router = project.in(file("router"))
.enablePlugins(ScalaJSPlugin, ScalaJSBundlerPlugin)
.dependsOn(core)

lazy val routerDom = project.in(file("router-dom"))
.settings(commonSettings: _*)
.settings(
name += "-router-dom",
npmDependencies in Compile ++= Seq(
"react-router-dom" -> ReactRouterVersion
),
(webpack in(Compile, fastOptJS)) := Seq(),
(webpack in(Compile, fullOptJS)) := Seq(),
publishArtifact := true
)
.enablePlugins(ScalaJSPlugin, ScalaJSBundlerPlugin)
.dependsOn(core, router)

lazy val redux = project.in(file("redux"))
.settings(commonSettings: _*)
.settings(
Expand Down Expand Up @@ -141,7 +158,7 @@ lazy val exampleRouting = project.in(file("example") / "routing")
name += "-routing"
)
.enablePlugins(ScalaJSPlugin, ScalaJSBundlerPlugin)
.dependsOn(core, router)
.dependsOn(core, routerDom)

lazy val exampleStyle = project.in(file("example") / "style")
.settings(exampleCommonSettings: _*)
Expand Down Expand Up @@ -182,10 +199,10 @@ lazy val exampleTest = project.in(file("example") / "test")
.settings(
name += "-example-test",
libraryDependencies ++= Seq(
"org.eclipse.jetty" % "jetty-server" % "9.3+",
"org.seleniumhq.selenium" % "selenium-java" % "2.+",
"org.eclipse.jetty" % "jetty-server" % "9.3.+",
"org.seleniumhq.selenium" % "selenium-java" % SeleniumVersion,

"org.scalatest" %% "scalatest" % "3.+"
"org.scalatest" %% "scalatest" % ScalaTestVersion
),
javaOptions ++= Seq(
s"-Dtarget.path.custom-virtual-dom=${(crossTarget in exampleCustomVirtualDOM).value}",
Expand All @@ -197,6 +214,7 @@ lazy val exampleTest = project.in(file("example") / "test")
s"-Dtarget.path.style=${(crossTarget in exampleStyle).value}",
s"-Dtarget.path.todo-app=${(crossTarget in exampleTodoApp).value}",
s"-Dtarget.path.todo-app-redux=${(crossTarget in exampleTodoAppRedux).value}",
// Just to build them
s"-Ddummy.custom-virtual-dom=${(webpack in fastOptJS in Compile in exampleCustomVirtualDOM).value}",
s"-Ddummy.helloworld=${(webpack in fastOptJS in Compile in exampleHelloWorld).value}",
s"-Ddummy.helloworld-function=${(webpack in fastOptJS in Compile in exampleHelloWorldFunction).value}",
Expand Down
12 changes: 2 additions & 10 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
# Facade for react and react-dom
# scalajs-reactjs

## API References

- [`React`](./src/main/scala/io/github/shogowada/scalajs/reactjs/React.scala)
- [`ReactDOM`](./src/main/scala/io/github/shogowada/scalajs/reactjs/ReactDOM.scala)
- [`VirtualDOM`](./src/main/scala/io/github/shogowada/scalajs/reactjs/VirtualDOM.scala)
- [`ReactClassSpec`](./src/main/scala/io/github/shogowada/scalajs/reactjs/classes/specs/ReactClassSpec.scala)
- [`ReactHTMLElements`](./src/main/scala/io/github/shogowada/scalajs/reactjs/elements/ReactHTMLElements.scala)
- [`SyntheticEvent`](./src/main/scala/io/github/shogowada/scalajs/reactjs/events/SyntheticEvent.scala)
- [`FormSyntheticEvent`](./src/main/scala/io/github/shogowada/scalajs/reactjs/events/FormSyntheticEvent.scala)
A facade for react and react-dom

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,15 @@ import io.github.shogowada.scalajs.reactjs.elements.ReactElement
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

/** Facade for react */
object React {

/** Returns [[ReactClass]] created by given [[ReactClassSpec]] */
def createClass[Props, State](spec: ReactClassSpec[Props, State]): ReactClass =
NativeCreateReactClass(spec.asNative)

/** Returns [[ReactElement]] created by given tag name, attributes, and children */
def createElement(tagName: String, attributes: js.Any, children: js.Any*): ReactElement =
NativeReact.createElement(tagName, attributes, children: _*)

/** Returns [[ReactElement]] created by given [[ReactClassSpec]] */
def createElement[Props, State](spec: ReactClassSpec[Props, State]): ReactElement = {
val reactClass = createClass(spec)
NativeReact.createElement(reactClass)
}

/** Returns [[ReactElement]] created by given [[ReactClassSpec]] and its props */
def createElement[Props, State](spec: ReactClassSpec[Props, State], props: Props): ReactElement = {
val reactClass = createClass(spec)
NativeReact.createElement(reactClass, ReactClassSpec.propsToNative(props))
}

/** Returns [[ReactElement]] created by given [[ReactClassSpec]], its props, and children */
def createElement[Props, State](spec: ReactClassSpec[Props, State], props: Props, children: js.Any*): ReactElement = {
val reactClass = createClass(spec)
NativeReact.createElement(reactClass, ReactClassSpec.propsToNative(props), children: _*)
}

/** Returns [[ReactElement]] created by given [[ReactClass]], its props, and children */
def createElement(reactClass: ReactClass, props: js.Any, children: js.Any*): ReactElement = {
def createElement(reactClass: ReactClass, props: js.Any, children: js.Any*): ReactElement =
NativeReact.createElement(reactClass, props, children: _*)
}

def createElement(reactClass: ReactClass): ReactElement =
NativeReact.createElement(reactClass)
Expand All @@ -52,9 +28,7 @@ object NativeReact extends js.Object {

def createElement(reactClass: ReactClass): ReactElement = js.native

def createElement(reactClass: ReactClass, attributes: js.Any): ReactElement = js.native

def createElement(reactClass: ReactClass, props: js.Any, children: js.Any*): ReactElement = js.native
def createElement(reactClass: ReactClass, attributes: js.Any, children: js.Any*): ReactElement = js.native
}

@js.native
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,13 @@
package io.github.shogowada.scalajs.reactjs

import io.github.shogowada.scalajs.reactjs.classes.specs.ReactClassSpec
import io.github.shogowada.scalajs.reactjs.elements.ReactElement
import org.scalajs.dom

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

/** Facade for react-dom */
object ReactDOM {
/** Mounts [[ReactClassSpec]] to given node */
def render[Props, State](reactClassSpec: ReactClassSpec[Props, State], node: dom.Node): Unit = {
render(React.createElement(reactClassSpec), node)
}

/** Mounts [[ReactClassSpec]] with its props to given node */
def render[Props, State](reactClassSpec: ReactClassSpec[Props, State], props: Props, node: dom.Node): Unit = {
render(React.createElement(reactClassSpec, props), node)
}

/** Mounts [[ReactElement]] to given node */
def render(element: ReactElement, node: dom.Node): Unit = {
NativeReactDOM.render(element, node)
}
}

@js.native
@JSImport("react-dom", JSImport.Namespace)
object NativeReactDOM extends js.Object {

def render(element: ReactElement, node: dom.Node): Unit = js.native
object ReactDOM extends js.Object {
def render(element: ReactElement, node: dom.Node): js.Any = js.native
}
Loading

0 comments on commit fbe1403

Please sign in to comment.