【问题标题】:In scalajs with scalajs-react how do I pass a scalajs defined component to a javascript defined component?在带有 scalajs-react 的 scalajs 中,如何将 scalajs 定义的组件传递给 javascript 定义的组件?
【发布时间】:2017-02-04 21:20:27
【问题描述】:

我的问题也在这里: https://gist.github.com/somanythings/8c3d34de754af311d7826ea837d160b4

将 scalajs 与 japgolly 的 scalajs-react (https://github.com/japgolly/scalajs-react) 库一起使用。我正在尝试包装烤盘网格http://griddlegriddle.github.io/Griddle/customization.html 我想要一个自定义列,为此需要我传递一个包含组件的 columnMetadata 结构。

当我这样做时,我可以渲染一个没有属性的 scalajs 定义的组件,但是如果我尝试通过 renderP 访问属性,或者通过 renderS 访问属性,它们在渲染函数的范围内都是未定义的。如果我在浏览器中调试,它们的名称是绑定的,并且确实具有预期值。

当我休息时

def renderP(f: (DuringCallbackU[P, S, B], P) => ReactElement): Out =
  render($ => f($, $.props))

那么$.props 是未定义的

我错过了什么?它是 ReactComponentB 调度中的简单输入问题吗? 它是否与https://github.com/japgolly/scalajs-react/issues/157 有某种关系,而我只是没看到有什么关系?

// Confusion over how to pass a scalajs defined component to a javascript defined component

object GriddleComponentWrapper {
  // for customComponent I've tried js.Any, ReactComponentU 
  @ScalaJSDefined
  class ColumnMeta(val columnName: String, val order: Int, val customComponent: ReactClass=null) extends js.Object
}

case class GriddleComponentWrapper(results: js.Any, //Seq[Map[String, Any]],
                                   columns: Seq[String],
                                   columnMeta: Option[Seq[ColumnMeta]] = None,
                                   showSettings: Boolean = true,
                                   showFilter: Boolean = true
                                  ) {
  def toJS = {
    val p = js.Dynamic.literal()
    p.updateDynamic("results")(results)
    p.updateDynamic("columns")(columns)
    p.updateDynamic("showSettings")(showSettings)
    p.updateDynamic("showFilter")(showFilter)

    (columnMeta).foreach { case cm => p.updateDynamic("columnMetadata")(cm.toJsArray) }

    p
  }

  def apply(children: ReactNode*) = {
    val f = React.asInstanceOf[js.Dynamic].createFactory(js.Dynamic.global.Bundle.griddle) // access real js component , make sure you wrap with createFactory (this is needed from 0.13 onwards)
    f(toJS, children.toJsArray).asInstanceOf[ReactComponentU_]
  }

}

object MyTestGrid {

  @js.native
  class ColumnMetaProps(val data: js.Object, val rowData: js.Object, val metadata: js.Object) extends js.Object

  // I've tried making the Props argument js.Dynamic, and also the ColumnMetaProps above
  @JSExport
  val testComp = ReactComponentB[js.Dynamic]("Mine").renderP(
    (sc, props: js.Dynamic) => {
      //when debugging this in the browser, 'sc' and 'props' have inspectable object values with the expected members in the browser 
      //dev tools, BUT, they're undefined 
      log.info(s"what is ${sc.props}")
      log.info(s"what is $props")
      val string: Frag = if (!js.isUndefined(props)) props.data.toString() else "nothing!"
      <.h1(string)
    }).build

   @JSExport 
   val aCompletelyStaticComponentWithNoPropsWillWork = ReactComponentB[js.Dynamic]("MyStaticComponent").renderP(
    (sc, props: js.Dynamic) =>  <.h1("this renders!!") ).build


// am I passing the right thing to columnmeta with testComp.reactClass? 
 val columnMeta = (new ColumnMeta("c1", 1, testComp.reactClass) :: Nil).toJsArray

  val results = Seq(
    js.Dynamic.literal("c1" -> "row1c1", "c2" -> "row1c2"),
    ).toJsArray

  val component = ReactComponentB[js.Dynamic]("MyTestGrid")
    .render_P {
      props =>
        GriddleComponentWrapper(results, columns = "c1" :: "c2" :: Nil, columnMeta = Some(columnMeta))()
    }.build

  def apply() = component
}

【问题讨论】:

  • 不是我的问题的解决方法,而是一种解决方法,所以我在评论而不是“回答”,希望它可以帮助其他人。我这样定义了我的自定义组件:val myCustomComp: js.Function = (props: ColumnMetaProps) =&gt; { log.info(s"here i can see ${props.data.toString()}") &lt;.h1(s"some wrapper ${props.data.toString()}").render } 然后将 myCustomComp 传递给 columnMetadata
  • 我在 gitter 上问了同样的问题:gitter.im/japgolly/scalajs-react?at=57fdda6bdfe82a365b1a71ad
  • 你在哪里将 scalajs 组件传递给 js 组件? gist.github.com/somanythings/8c3d34de754af311d7826ea837d160b4 ?我在这里只能看到 scalajs 代码......你的意思是这里 gist.github.com/somanythings/…
  • @jhegedus griddle 是一个 js react 组件。我的烤盘包装器是一个 scalajs 代理。

标签: scala.js scalajs-react


【解决方案1】:

React.JS 要求 props 和 state 始终是一个对象(或 null)。使用单个 Scala 值(如原语或案例类实例)会导致 React.JS 中的异常。因此,在 scalajs-react 中,为了允许用户以类型安全的方式使用任何 props/state 类型,在后台使用了一个具有单个键 "v" 的对象。 IE。不是直接使用123,而是使用{v:123}

您可能需要在代码中适应这种装箱。

现在,在下一个主要版本(参见“neo”分支)中,组件的表示得到了极大的改进,不再像我刚才描述的那样隐藏魔法。虽然 v0.x 并非旨在促进 JS↔Scala 组件互操作,但它在 neo 中将是明确的、显而易见的并且希望是微不足道的。

【讨论】:

  • 这在实践中意味着什么?有没有一个简单的例子我该怎么做?
  • 我个人不知道一个例子,但我建议在 scalajs-react gitter 聊天室询问。我认为那里有一两个人有类似的用例。此外,如果您找到或创建了一个示例,请考虑将其贡献给 scalajs-react 的文档,以帮助其他人在未来遇到同样的问题。祝你好运。
  • 嗨,谢谢你的提示,我就是这样做的,并得到了帮助,我在这里记录了解决方案:github.com/jhegedus42/scalajs-react-playaround/wiki/…
猜你喜欢
  • 2018-09-12
  • 2016-01-12
  • 2017-06-12
  • 1970-01-01
  • 2015-10-08
  • 2018-09-13
  • 2014-08-28
  • 1970-01-01
  • 2017-04-21
相关资源
最近更新 更多