是否有明确的途径可以实现在 ScalaJS + React 中广泛使用上下文的 React 组件?
Is there a clear path by which I could implement a React Component that uses context extensively in ScalaJS + React?
This component from react-sticky
is one of two in the library.
container
,它初始化并向下传递一个 context
到它的 child
...
sticky
,利用context
和滚动位置来实现粘头效果。
我刚刚花了大约两个小时或更多时间将它费力地移植到 scalajs
中的 ReactJS
中,并且我已将到目前为止所做的粘贴在下面。它不编译;仍然有松动的电线。
我开始认为我应该放弃,因为也许我的道路不是一条好路。我试图做的是用 ParentProps
消除 sjs
库中不可用的 context
的使用,并将其状态传递给 child 并返回。
然而,考虑到涉及的移动部件数量,我对这甚至可能奏效失去了信心。我想知道是否有更好的移植方法。
package shindig.frontend.component.layout
import fr.iscpif.scaladget.mapping.ace.PlaceHolder
import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom._
import japgolly.scalajs.react.vdom.prefix_<^._
import org.scalajs.dom.html.Div
import org.scalajs.dom.window
import org.scalajs.dom.raw.ClientRect
import scalacss.Defaults._
object StickyComponent {
case class Props(
isActive: Boolean = true,
className: String = "",
style: Seq[StyleA] = Seq(),
stickyClassName: String = "",
stickyStyle: Seq[StyleA] = Seq(),
offsetTop: Double = 0,
offsetBottom: Double = 0,
stickyStateChange: () ⇒ Callback = () ⇒ (),
contextProps: StickyContainer.Props = StickyContainer.Props()
)
case class State(isSticky: Boolean = false, origin: PlaceHolder)
class Backend($: BackendScope[Props, State]) {
def componentDidMount(): Unit = {
}
def getNode: TopNode = ReactDOM.findDOMNode($)
def getRect = getNode.getBoundingClientRect()
def getY = window.pageYOffset
def getOrigin(y: Double): Double = getPlaceholderRef.top + y
def getPlaceholderRef = $.refs.apply[Div]("placeholder").get.getDOMNode().getBoundingClientRect()
def getProps: Props = $.props.runNow()
def isBelow(y: Double, contextProps: StickyContainer.Props): Boolean =
y + contextProps.offset >= getOrigin(y)
def isAbove(y: Double, contextProps: StickyContainer.Props, offset: Double): Boolean =
contextProps.offset <= contextProps.bottomOfRectOrNil - offset
def isStickyAt(y: Double, origin: Double): Boolean = {
val props = getProps
val y = getY
props.isActive && isBelow(y, props.contextProps) && isAbove(y, props.contextProps, props.offsetBottom)
}
def update() = $.setState(State(
))
}
}
object StickyContainer {
case class Props(
node: Option[TopNode] = None,
offset: Double = 0,
rect: Option[ClientRect] = None
) {
def bottomOfRectOrNil: Double = rect match {
case Some(r) ⇒ r.bottom
case None ⇒ 0
}
}
case class State(
node: Option[TopNode] = None,
offset: Double = 0,
rect: Option[_] = None
) {
def withNode(node: TopNode) =
State(Some(node), offset, rect)
}
class Backend($: BackendScope[Unit, State]) {
def componentDidMount(): Unit = {
$.modState(_.withNode(ReactDOM.findDOMNode($)))
}
def render() = {
<.div(
$.propsChildren()
)
}
}
val component =
ReactComponentB[Unit]("StickyContainer")
.initialState(State())
.backend[Backend]($ ⇒ new Backend($))
.renderBackend
.build
}
所以实际上有两个答案:第一个答案是,我仍然不知道您如何在 scalajs
和 reactjs
中使用 context
,但第二个答案是,没关系,自从这次以来,我已经毫无问题地移植了其他十个 react
库。我专注于不需要移植的移植方法。
您只需按照 https://github.com/chandu0101/scalajs-react-components/blob/master/doc/InteropWithThirdParty.md 中的指南进行操作即可。如果您已经搜索了一段时间,您可能已经看到了这个并且可能不相信它会起作用(一开始我不太明白它会起作用),因为您所做的只是复制 Props
并创建一个人造构造函数。好吧,这就是您需要做的全部 - 很可能 - 所以在处理此任务之前尝试仅移植该页面上需要的内容。
This component from react-sticky
is one of two in the library.
container
,它初始化并向下传递一个context
到它的child
...sticky
,利用context
和滚动位置来实现粘头效果。
我刚刚花了大约两个小时或更多时间将它费力地移植到 scalajs
中的 ReactJS
中,并且我已将到目前为止所做的粘贴在下面。它不编译;仍然有松动的电线。
我开始认为我应该放弃,因为也许我的道路不是一条好路。我试图做的是用 ParentProps
消除 sjs
库中不可用的 context
的使用,并将其状态传递给 child 并返回。
然而,考虑到涉及的移动部件数量,我对这甚至可能奏效失去了信心。我想知道是否有更好的移植方法。
package shindig.frontend.component.layout
import fr.iscpif.scaladget.mapping.ace.PlaceHolder
import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom._
import japgolly.scalajs.react.vdom.prefix_<^._
import org.scalajs.dom.html.Div
import org.scalajs.dom.window
import org.scalajs.dom.raw.ClientRect
import scalacss.Defaults._
object StickyComponent {
case class Props(
isActive: Boolean = true,
className: String = "",
style: Seq[StyleA] = Seq(),
stickyClassName: String = "",
stickyStyle: Seq[StyleA] = Seq(),
offsetTop: Double = 0,
offsetBottom: Double = 0,
stickyStateChange: () ⇒ Callback = () ⇒ (),
contextProps: StickyContainer.Props = StickyContainer.Props()
)
case class State(isSticky: Boolean = false, origin: PlaceHolder)
class Backend($: BackendScope[Props, State]) {
def componentDidMount(): Unit = {
}
def getNode: TopNode = ReactDOM.findDOMNode($)
def getRect = getNode.getBoundingClientRect()
def getY = window.pageYOffset
def getOrigin(y: Double): Double = getPlaceholderRef.top + y
def getPlaceholderRef = $.refs.apply[Div]("placeholder").get.getDOMNode().getBoundingClientRect()
def getProps: Props = $.props.runNow()
def isBelow(y: Double, contextProps: StickyContainer.Props): Boolean =
y + contextProps.offset >= getOrigin(y)
def isAbove(y: Double, contextProps: StickyContainer.Props, offset: Double): Boolean =
contextProps.offset <= contextProps.bottomOfRectOrNil - offset
def isStickyAt(y: Double, origin: Double): Boolean = {
val props = getProps
val y = getY
props.isActive && isBelow(y, props.contextProps) && isAbove(y, props.contextProps, props.offsetBottom)
}
def update() = $.setState(State(
))
}
}
object StickyContainer {
case class Props(
node: Option[TopNode] = None,
offset: Double = 0,
rect: Option[ClientRect] = None
) {
def bottomOfRectOrNil: Double = rect match {
case Some(r) ⇒ r.bottom
case None ⇒ 0
}
}
case class State(
node: Option[TopNode] = None,
offset: Double = 0,
rect: Option[_] = None
) {
def withNode(node: TopNode) =
State(Some(node), offset, rect)
}
class Backend($: BackendScope[Unit, State]) {
def componentDidMount(): Unit = {
$.modState(_.withNode(ReactDOM.findDOMNode($)))
}
def render() = {
<.div(
$.propsChildren()
)
}
}
val component =
ReactComponentB[Unit]("StickyContainer")
.initialState(State())
.backend[Backend]($ ⇒ new Backend($))
.renderBackend
.build
}
所以实际上有两个答案:第一个答案是,我仍然不知道您如何在 scalajs
和 reactjs
中使用 context
,但第二个答案是,没关系,自从这次以来,我已经毫无问题地移植了其他十个 react
库。我专注于不需要移植的移植方法。
您只需按照 https://github.com/chandu0101/scalajs-react-components/blob/master/doc/InteropWithThirdParty.md 中的指南进行操作即可。如果您已经搜索了一段时间,您可能已经看到了这个并且可能不相信它会起作用(一开始我不太明白它会起作用),因为您所做的只是复制 Props
并创建一个人造构造函数。好吧,这就是您需要做的全部 - 很可能 - 所以在处理此任务之前尝试仅移植该页面上需要的内容。