From e7509475050ab857938a2edf733eb863f7314f78 Mon Sep 17 00:00:00 2001 From: David Barri Date: Tue, 22 Mar 2022 18:46:01 +1100 Subject: [PATCH 1/2] Add `Reusability` for component refs --- .../japgolly/scalajs/react/Reusability.scala | 8 ++++++++ .../scalajs/react/core/ReusabilityTest.scala | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/library/coreGeneric/src/main/scala/japgolly/scalajs/react/Reusability.scala b/library/coreGeneric/src/main/scala/japgolly/scalajs/react/Reusability.scala index 08de6da5f..df2de38f6 100644 --- a/library/coreGeneric/src/main/scala/japgolly/scalajs/react/Reusability.scala +++ b/library/coreGeneric/src/main/scala/japgolly/scalajs/react/Reusability.scala @@ -351,6 +351,14 @@ object Reusability extends ReusabilityMacros with ScalaVersionSpecificReusabilit implicit def refFullF[F[_], I, A, O]: Reusability[Ref.FullF[F, I, A, O]] = refRaw[A | Null].contramap(_.raw) + /** Updating a reference doesn't trigger a component re-rendering, nor is the current reference value considered for reusability. + * + * Any `map`/`contramap` functions installed in the ref are ignored for the sake of reusability. If this is undesirable, pass around + * a [[Reusable]] ref instead. + */ + implicit def refToComponentF[F[_], I, R, O, C]: Reusability[Ref.ToComponentF[F, I, R, O, C]] = + refFullF[F, I, R, O].narrow + /** Updating a reference doesn't trigger a component re-rendering, nor is the current reference value considered for reusability. */ implicit def nonEmptyRefHandleF[F[_], A]: Reusability[NonEmptyRef.HandleF[F, A]] = refRaw[A].contramap(_.raw) diff --git a/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala b/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala index 1d3d84d0c..8b7518832 100644 --- a/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala +++ b/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala @@ -120,6 +120,13 @@ object ReusabilityTest extends TestSuite { assertEq(r.test(a, b), a == b) } + private def testByRef[A: Reusability](create: => A)(implicit l: Line): Unit = { + val a = create + val b = create + assertEq(a ~=~ a, true) + assertEq(a ~=~ b, false) + } + override def tests = Tests { "macros" - { @@ -477,5 +484,13 @@ object ReusabilityTest extends TestSuite { assert(BigInt("10") ~=~ BigInt("10")) assert(BigInt("10") ~/~ BigInt("11")) } + + "ref" - { + "handle" - testByRef(Ref[Int]: Ref.Handle[Int]) + "simple" - testByRef(Ref[Int]) + "vdom" - testByRef(Ref.toAnyVdom()) + "scala" - testByRef(Ref.toScalaComponent(SampleComponent1.component)) + "js" - testByRef(Ref.toJsComponent(JsComponentEs6PTest.Component)) + } } } From 5edc72b5f390e52695855aed6da836abaff597be Mon Sep 17 00:00:00 2001 From: David Barri Date: Tue, 22 Mar 2022 18:52:56 +1100 Subject: [PATCH 2/2] Give `NonEmptyRef` `Reusability` a test too --- .../scala/japgolly/scalajs/react/core/ReusabilityTest.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala b/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala index 8b7518832..bc47a2757 100644 --- a/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala +++ b/library/tests/src/test/scala/japgolly/scalajs/react/core/ReusabilityTest.scala @@ -492,5 +492,10 @@ object ReusabilityTest extends TestSuite { "scala" - testByRef(Ref.toScalaComponent(SampleComponent1.component)) "js" - testByRef(Ref.toJsComponent(JsComponentEs6PTest.Component)) } + + "nonEmptyRef" - { + "handle" - testByRef(NonEmptyRef[Int](6): NonEmptyRef.Handle[Int]) + "simple" - testByRef(NonEmptyRef[Int](6)) + } } }