Last active
August 20, 2017 00:04
-
-
Save japgolly/8c14b53b15b922cb79d69e79c76538ec to your computer and use it in GitHub Desktop.
Callback Reusability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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