This component from react-sticky
is one of two in the library.是否有一条清晰的路径可以实现在ScalaJS + React中广泛使用上下文的React组件?
container
,初始化和向下传递一个context
其child
...sticky
,其使用context
和滚动位置以实现粘头的效果。
我只花了大约两个小时以上的移植这scalajs
费力地进入ReactJS
,我已经粘贴下面是我迄今完成的。它不编译;仍然有松动的电线。
我开始认为我应该放弃,因为也许我的道路不是很好。我试图做的是消除使用context
这是sjs
库中不可用与ParentProps
并将其状态传递给孩子和后面。
但是,考虑到所涉及的移动部件的数量,我对此失去了信心,甚至可能会发挥作用。我需要知道是否有更好的方法或不需要移植。
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
}