使用 Diode 错误渲染 React (scalajs-react) 组件
Rendering React (scalajs-react) component with Diode error
我将使用 Diode 来管理具有单向数据流的应用程序状态。我使用 Playframework 2.4 和 Scala.js,这里是客户端子项目 build.sbt
的一部分:
libraryDependencies ++= Seq(
...
"me.chrons" %%% "diode" % "1.0.0",
"me.chrons" %%% "diode-react" % "1.0.0",
"com.github.japgolly.scalajs-react" %%% "core" % "0.11.3",
"com.github.japgolly.scalajs-react" %%% "extra" % "0.11.3"
),
我能够 运行 来自 scalajs-react 的基本样本,并决定扩展 Timer sample 以支持 Diode。我写了一个 Curcuit
对象:
object TimerCircuit extends Circuit[TimerRootModel] with ReactConnector[TimerRootModel] {
// initialModel and actionHanler implemented here
}
教程和示例没有向我们展示如何使用 ReactDOM.render(...)
渲染 React 组件,而是仅使用包 japgolly.scalajs.react.extra.router
。
但是,这次我不想使用路由器,只想将我的组件渲染到 HTML 根标记中,如下所示:
class ReactStateSampleView() {
case class State(secondsElapsed: Long)
class Backend($: BackendScope[ModelProxy[String], State]) {
val DefaultInterval: Long = 1000
//noinspection ScalaStyle
var interval: js.UndefOr[js.timers.SetIntervalHandle] = js.undefined
def tick: Callback = $.modState(s => State(s.secondsElapsed + 1))
def start: Callback = Callback {
interval = js.timers.setInterval(DefaultInterval)(tick.runNow())
}
def clear: Callback = Callback {
interval foreach js.timers.clearInterval
interval = js.undefined
}
def render(s: State): ReactTag =
<.div("Seconds elapsed: ", s.secondsElapsed)
}
val timer = ReactComponentB[ModelProxy[String]]("Timer")
.initialState(State(0))
.renderBackend[Backend]
.componentDidMount(_.backend.start)
.componentWillMount(_.backend.clear)
.build
val sc = TimerCircuit.connect(_.data)
ReactDOM.render(sc(p => timer(p)), dom.document.getElementById("timer"))
但是这部分
ReactDOM.render(sc(p => timer(p)), dom.document.getElementById("timer"))
不起作用。项目未编译并显示 "RuntimeException: There were linking errors"
如何解决问题?
更新
以下是链接错误和堆栈跟踪的确切消息:
[info] Fast optimizing C:\tmp\project\client\target\scala-2.11\client-fastopt.js
[error] Referring to non-existent class japgolly.scalajs.react.Callback$ResultGuard$
[error] called from diode.react.ReactConnector$$anonfun$wrap.apply(java.lang.Object)scala.Function0
[error] called from diode.react.ReactConnector$$anonfun$wrap.apply(java.lang.Object)java.lang.Object
[error] called from japgolly.scalajs.react.Internal$FnComposer$$anonfun$apply$$anonfun$apply.apply(java.lang.Object)java.lang.Object
[error] called from japgolly.scalajs.react.CompState$RootAccessor.modState(japgolly.scalajs.react.CompScope$CanSetState,scala.Function1,scala.Function0)scala.Unit
[error] called from japgolly.scalajs.react.CompState$RootAccessor.modState(java.lang.Object,scala.Function1,scala.Function0)scala.Unit
[error] called from japgolly.scalajs.react.CompState$WriteCallbackOps$class.modState(japgolly.scalajs.react.CompState$WriteCallbackOps,scala.Function1,scala.Function0)scala.Function0
[error] called from japgolly.scalajs.react.CompState$ReadCallbackWriteCallback.modState(scala.Function1,scala.Function0)scala.Function0
[error] called from org.example.client.playground.ReactStateSampleView$Backend.tick()scala.Function0
[error] called from org.example.client.playground.ReactStateSampleView$Backend$$anonfun$start.apply$mcV$sp()scala.Unit
...
Caused by: java.lang.RuntimeException: There were linking errors
at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.8.jar:na]
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:133) ~[na:na]
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:86) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun.apply(LinkerFrontend.scala:54) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun.apply(LinkerFrontend.scala:54) ~[na:na]
at org.scalajs.core.tools.logging.Logger$class.time(Logger.scala:28) ~[na:na]
at org.scalajs.sbtplugin.Loggers$SbtLoggerWrapper.time(Loggers.scala:7) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend.link(LinkerFrontend.scala:53) ~[na:na]
at org.scalajs.core.tools.linker.Linker$$anonfun$link.apply$mcV$sp(Linker.scala:50) ~[na:na]
at org.scalajs.core.tools.linker.Linker$$anonfun$link.apply(Linker.scala:49) ~[na:na]
链接错误表明 scalajs-react 和 Diode 之间存在二进制不兼容。从您的 libraryDependencies
来看,这听起来很合理,因为:
- 您依赖
scalajs-react-core
0.11.3,但是
- 您还依赖
diode
1.0.0,which depends on scalajs-react-core
0.11.1。
如果 scalajs-react-core
从 0.11.1 到 0.11.3 有一个二进制不兼容的变化,那可以解释你的问题。
如果我是对的,你可以通过升级到 Diode 1.1.0 来解决这个问题,which uses scalajs-react-core
0.11.3。
我将使用 Diode 来管理具有单向数据流的应用程序状态。我使用 Playframework 2.4 和 Scala.js,这里是客户端子项目 build.sbt
的一部分:
libraryDependencies ++= Seq(
...
"me.chrons" %%% "diode" % "1.0.0",
"me.chrons" %%% "diode-react" % "1.0.0",
"com.github.japgolly.scalajs-react" %%% "core" % "0.11.3",
"com.github.japgolly.scalajs-react" %%% "extra" % "0.11.3"
),
我能够 运行 来自 scalajs-react 的基本样本,并决定扩展 Timer sample 以支持 Diode。我写了一个 Curcuit
对象:
object TimerCircuit extends Circuit[TimerRootModel] with ReactConnector[TimerRootModel] {
// initialModel and actionHanler implemented here
}
教程和示例没有向我们展示如何使用 ReactDOM.render(...)
渲染 React 组件,而是仅使用包 japgolly.scalajs.react.extra.router
。
但是,这次我不想使用路由器,只想将我的组件渲染到 HTML 根标记中,如下所示:
class ReactStateSampleView() {
case class State(secondsElapsed: Long)
class Backend($: BackendScope[ModelProxy[String], State]) {
val DefaultInterval: Long = 1000
//noinspection ScalaStyle
var interval: js.UndefOr[js.timers.SetIntervalHandle] = js.undefined
def tick: Callback = $.modState(s => State(s.secondsElapsed + 1))
def start: Callback = Callback {
interval = js.timers.setInterval(DefaultInterval)(tick.runNow())
}
def clear: Callback = Callback {
interval foreach js.timers.clearInterval
interval = js.undefined
}
def render(s: State): ReactTag =
<.div("Seconds elapsed: ", s.secondsElapsed)
}
val timer = ReactComponentB[ModelProxy[String]]("Timer")
.initialState(State(0))
.renderBackend[Backend]
.componentDidMount(_.backend.start)
.componentWillMount(_.backend.clear)
.build
val sc = TimerCircuit.connect(_.data)
ReactDOM.render(sc(p => timer(p)), dom.document.getElementById("timer"))
但是这部分
ReactDOM.render(sc(p => timer(p)), dom.document.getElementById("timer"))
不起作用。项目未编译并显示 "RuntimeException: There were linking errors"
如何解决问题?
更新
以下是链接错误和堆栈跟踪的确切消息:
[info] Fast optimizing C:\tmp\project\client\target\scala-2.11\client-fastopt.js
[error] Referring to non-existent class japgolly.scalajs.react.Callback$ResultGuard$
[error] called from diode.react.ReactConnector$$anonfun$wrap.apply(java.lang.Object)scala.Function0
[error] called from diode.react.ReactConnector$$anonfun$wrap.apply(java.lang.Object)java.lang.Object
[error] called from japgolly.scalajs.react.Internal$FnComposer$$anonfun$apply$$anonfun$apply.apply(java.lang.Object)java.lang.Object
[error] called from japgolly.scalajs.react.CompState$RootAccessor.modState(japgolly.scalajs.react.CompScope$CanSetState,scala.Function1,scala.Function0)scala.Unit
[error] called from japgolly.scalajs.react.CompState$RootAccessor.modState(java.lang.Object,scala.Function1,scala.Function0)scala.Unit
[error] called from japgolly.scalajs.react.CompState$WriteCallbackOps$class.modState(japgolly.scalajs.react.CompState$WriteCallbackOps,scala.Function1,scala.Function0)scala.Function0
[error] called from japgolly.scalajs.react.CompState$ReadCallbackWriteCallback.modState(scala.Function1,scala.Function0)scala.Function0
[error] called from org.example.client.playground.ReactStateSampleView$Backend.tick()scala.Function0
[error] called from org.example.client.playground.ReactStateSampleView$Backend$$anonfun$start.apply$mcV$sp()scala.Unit
...
Caused by: java.lang.RuntimeException: There were linking errors
at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.8.jar:na]
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:133) ~[na:na]
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:86) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun.apply(LinkerFrontend.scala:54) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun.apply(LinkerFrontend.scala:54) ~[na:na]
at org.scalajs.core.tools.logging.Logger$class.time(Logger.scala:28) ~[na:na]
at org.scalajs.sbtplugin.Loggers$SbtLoggerWrapper.time(Loggers.scala:7) ~[na:na]
at org.scalajs.core.tools.linker.frontend.LinkerFrontend.link(LinkerFrontend.scala:53) ~[na:na]
at org.scalajs.core.tools.linker.Linker$$anonfun$link.apply$mcV$sp(Linker.scala:50) ~[na:na]
at org.scalajs.core.tools.linker.Linker$$anonfun$link.apply(Linker.scala:49) ~[na:na]
链接错误表明 scalajs-react 和 Diode 之间存在二进制不兼容。从您的 libraryDependencies
来看,这听起来很合理,因为:
- 您依赖
scalajs-react-core
0.11.3,但是 - 您还依赖
diode
1.0.0,which depends onscalajs-react-core
0.11.1。
如果 scalajs-react-core
从 0.11.1 到 0.11.3 有一个二进制不兼容的变化,那可以解释你的问题。
如果我是对的,你可以通过升级到 Diode 1.1.0 来解决这个问题,which uses scalajs-react-core
0.11.3。