You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.8 KiB

4 years ago
  1. package com.example.playscalajsreact.component
  2. import com.example.playscalajsreact.model.MyGlobalState
  3. import japgolly.scalajs.react.vdom.VdomElement
  4. import japgolly.scalajs.react._
  5. import japgolly.scalajs.react.vdom.html_<^._
  6. import com.example.playscalajsreact.route.AppRouter
  7. import com.example.playscalajsreact.model.User
  8. import japgolly.scalajs.react.extra.StateSnapshot
  9. // import com.softwaremill.quicklens._
  10. import com.example.playscalajsreact.model._
  11. object Top {
  12. final class Backend($ : BackendScope[Unit, Data]) {
  13. private val setStateFn =
  14. StateSnapshot.withReuse.prepareVia($)
  15. def render(state: Data): VdomElement = {
  16. val ss = setStateFn(state)
  17. // Middle.Props("Demo", ss).render
  18. Middle(Middle.Props("Demo", ss))
  19. }
  20. }
  21. val Comp = ScalaComponent
  22. .builder[Unit]
  23. .initialState(Data(123, "hello"))
  24. .renderBackend[Backend]
  25. .build
  26. }
  27. object Top2 {
  28. import japgolly.scalajs.react.vdom.all._
  29. import japgolly.scalajs.react.MonocleReact._
  30. final class Backend($ : BackendScope[Unit, MyGlobalState]) {
  31. private val setStateFn =
  32. StateSnapshot.withReuse.prepareVia($)
  33. def render(state: MyGlobalState): VdomElement = {
  34. // val ss = StateSnapshot.zoomL(MyGlobalState.user)(state).setStateVia($)
  35. // val ss2 = ss.xmapState(u => Snappy.State(u))(_.user)
  36. // div(Snappy.Props(ss2).render)
  37. val ss = setStateFn(state)
  38. div(
  39. // Middle2.Props("Middle2", ss).render,
  40. AppRouter.router(AppRouter.Props(ss)),
  41. "Value: ",
  42. state.user.map(_.username)
  43. )
  44. }
  45. }
  46. val Top2Component = ScalaComponent
  47. .builder[Unit]("Top2")
  48. .initialState(MyGlobalState(Some(User("testuser"))))
  49. // .initialState(MyGlobalState.empty)
  50. .renderBackend[Backend]
  51. .build
  52. def apply(): VdomElement = Top2Component()
  53. }
  54. object Middle2 {
  55. import japgolly.scalajs.react.MonocleReact._
  56. import monocle.macros.syntax.lens._
  57. import monocle.std.option._
  58. import monocle.macros.GenIso
  59. import cats.implicits._
  60. // val navigateToUsername = GenIso[MyGlobalState, Option[User]]
  61. // .composePrism(GenIso[User, String].asPrism.below[Option])
  62. val navigateToUsername =
  63. MyGlobalState.user.composePrism(GenIso[User, String].asPrism.below[Option])
  64. final case class Props(name: String, ss: StateSnapshot[MyGlobalState]) {
  65. @inline def render: VdomElement = Comp(this)
  66. }
  67. implicit def reusability: Reusability[Props] =
  68. Reusability.derive
  69. final class Backend($ : BackendScope[Props, Unit]) {
  70. // Method 2: StateSnapshot.withReuse.zoomL.prepareViaProps
  71. // Notice that we're using a normal lens here instead of a Reusable[lens]
  72. private val ssStrFn =
  73. StateSnapshot.withReuse.zoomL(MyGlobalState.user).prepareViaProps($)(_.ss)
  74. def render(p: Props): VdomElement = {
  75. val x = p.ss.zoomStateO(navigateToUsername)
  76. val y = x.map(_.xmapState(_ => 1)(_ => None))
  77. // Method 1: ss.withReuse.zoomStateL
  78. // val ssI: StateSnapshot[Int] = p.ss.zoomStateL(Data.reusableLens.int)
  79. // Method 2: StateSnapshot.withReuse.zoomL.prepareViaProps
  80. // val ssS: StateSnapshot[String] =
  81. // ssStrFn(p.ss.value)
  82. val ss4 = p.ss.zoomStateL(MyGlobalState.user)
  83. // val ss5 = p.ss.zoomStateO(navigateToUsername.asOptional)
  84. // val ss6 =
  85. // ss5.map(_.xmapState(_.map(n => User(n)))(_.map(u => u.username)))
  86. // ss5.foreach(_.modState(e => e))
  87. // val x = p.ss.value.lens(_.user.getOrElse(User.empty).username)
  88. // p.ss.zoomStateO()
  89. val ss2 = ss4.xmapState(u => Snappy.State(u))(_.user)
  90. <.div(
  91. <.h3(p.name),
  92. <.div("Snappy", Snappy.Props(ss2).render)
  93. )
  94. }
  95. }
  96. val Comp = ScalaComponent
  97. .builder[Props]
  98. .renderBackend[Backend]
  99. // .configure(Reusability.shouldComponentUpdate)
  100. .build
  101. def apply(_props: Props): VdomElement = { Comp(_props) }
  102. }
  103. object Snappy {
  104. final case class Props(state: StateSnapshot[State]) {
  105. @inline def render: VdomElement = Component(this)
  106. }
  107. //implicit val reusabilityProps: Reusability[Props] =
  108. // Reusability.derive
  109. final case class State(user: Option[User])
  110. object State {
  111. def empty = State(user = None)
  112. //implicit val reusability: Reusability[State] =
  113. // Reusability.derive
  114. }
  115. final class Backend($ : BackendScope[Props, Unit]) {
  116. import com.softwaremill.quicklens._
  117. def render(p: Props): VdomNode = {
  118. val s = p.state.value
  119. <.div("Test", s.user.map(u => {
  120. <.div(
  121. "Username",
  122. u.username,
  123. ^.onClick --> p.state.modState(
  124. _.modify(_.user.each.username).using(_ + "c")
  125. )
  126. )
  127. }))
  128. }
  129. }
  130. val Component = ScalaComponent
  131. .builder[Props]("Snappy")
  132. .renderBackend[Backend]
  133. //.configure(Reusability.shouldComponentUpdate)
  134. .build
  135. }