Skip to content

Instantly share code, notes, and snippets.

@oyvindberg
Created August 21, 2015 12:26
Show Gist options
  • Select an option

  • Save oyvindberg/f43b3edf1b681c78cd61 to your computer and use it in GitHub Desktop.

Select an option

Save oyvindberg/f43b3edf1b681c78cd61 to your computer and use it in GitHub Desktop.
import japgolly.scalajs.react.BackendScope
import japgolly.scalajs.react.extra._
import scalaz.syntax.id._
final case class CachingBackendScope[P: Reusability, S: Reusability]
(b: BackendScope[P, S]){ outer ⇒
type PropVal[O] = ReactVal[P, O]
type StateVal[O] = ReactVal[(P, S), O]
implicit class PropValX[O](p: PropVal[O]){
def stateful: StateVal[O] = p.imap[(P, S)](p => (p, b.state))(_._1)
}
def stateVal[O](f: (P, S) ⇒ O): StateVal[O] =
ReactVal[(P, S), O]((b.props, b.state))(f.tupled)
def propsVal[O](f: P ⇒ O): PropVal[O] =
ReactVal[P, O](b.props)(f)
}
class ReactVal[I: Reusability, O] private[ReactVal](_i: ⇒ I)(mapper: I ⇒ O){
private var cached: Option[(I, O)] = None
def value: O =
(_i, cached) match {
case (i1, Some((i2, v))) if i1 ~=~ i2 ⇒ v
case (i, _) ⇒
mapper(i).unsafeTap(v ⇒ cached = Some((i, v)))
}
def imap[NI: Reusability](to: I ⇒ NI)(from: NI ⇒ I): ReactVal[NI, O] =
new ReactVal[NI, O](to(_i))(mapper compose from)
def map[OO](ff: O ⇒ OO): ReactVal[I, OO] =
new ReactVal[I, OO](_i)(mapper andThen ff)
}
object ReactVal{
def ident[I: Reusability](i: ⇒ I): ReactVal[I, I] =
new ReactVal[I, I](i)(identity)
def apply[I: Reusability, O](i: ⇒ I)(f: I ⇒ O): ReactVal[I, O] =
new ReactVal[I, O](i)(f)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment