Skip to content

Instantly share code, notes, and snippets.

@japgolly
Last active August 20, 2017 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save japgolly/8c14b53b15b922cb79d69e79c76538ec to your computer and use it in GitHub Desktop.
Save japgolly/8c14b53b15b922cb79d69e79c76538ec to your computer and use it in GitHub Desktop.
Callback Reusability
import japgolly.scalajs.react._
import japgolly.scalajs.react.extra._
import japgolly.scalajs.react.vdom.html_<^._
object NotReusable {
final case class Props(name: String, update: Callback)
final class Backend($: BackendScope[Props, Unit]) {
def render(p: Props): VdomElement =
<.button(p.name, ^.onClick --> p.update) // <--------- Uses p.update which isn't Reusable
}
val Component = ScalaComponent.builder[Props]("")
.renderBackend[Backend]
.build
}
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
object Safe {
final case class Props(name: String, update: Reusable[Callback])
implicit val reusabilityProps: Reusability[Props] =
Reusability.caseClass
final class Backend($: BackendScope[Props, Unit]) {
def render(p: Props): VdomElement =
<.button(p.name, ^.onClick --> p.update)
}
val Component = ScalaComponent.builder[Props]("")
.renderBackend[Backend]
.configure(Reusability.shouldComponentUpdate)
.build
}
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
/** This is dangerous because the type system isn't sophisticated enough to support this and you have to just rely on
* devs' eyes.
*
* Anything is safely reusable so long as:
* 1. it's not accessed via the component's render method
* 2. it's only accessed from within other Callbacks
*/
object SafeButDangerous {
final case class Props(name: String, update: Callback)
implicit val reusabilityProps: Reusability[Props] =
Reusability.caseClassExcept('update) // <--------- Excluding .update from Reusability logic = dangerous
final class Backend($: BackendScope[Props, Unit]) {
val update: Callback =
$.props.flatMap(_.update) // <--------- Uses p.update access inside another Callback = safe
def render(p: Props): VdomElement =
<.button(p.name, ^.onClick --> update) // <--------- Doesn't use p.update
}
val Component = ScalaComponent.builder[Props]("")
.renderBackend[Backend]
.configure(Reusability.shouldComponentUpdate)
.build
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment