Skip to content

Commit

Permalink
Merge pull request #1089 from japgolly/usememo-reuse
Browse files Browse the repository at this point in the history
Reusability in functional components via React.memo instead of class component
  • Loading branch information
rpiaggio authored Jan 28, 2024
2 parents 9e5ab69 + 8ec42ef commit 3c0f6fa
Showing 1 changed file with 17 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package japgolly.scalajs.react.hooks

import japgolly.microlibs.types.NaturalComposition
import japgolly.scalajs.react.internal.ShouldComponentUpdateComponent
import japgolly.scalajs.react.internal.CoreGeneral.ScalaFnComponent
import japgolly.scalajs.react.util.DefaultEffects
import japgolly.scalajs.react.vdom.VdomNode
import japgolly.scalajs.react.{PropsChildren, Reusability, Reusable}
import japgolly.scalajs.react.{PropsChildren, React, Reusability, Reusable}

final class CustomHook[I, O] private[CustomHook] (val unsafeInit: I => O) extends AnyVal {

Expand Down Expand Up @@ -206,9 +206,21 @@ object CustomHook {
def reusableByDeps[D, A](create: (D, Int) => A)(implicit r: Reusability[D]): CustomHook[() => D, Reusable[A]] =
reusableDeps[D].map { case (d, rev) => Reusable.implicitly(rev).withValue(create(d, rev)) }

def shouldComponentUpdate[D](render: D => VdomNode)(implicit r: Reusability[D]): CustomHook[() => D, VdomNode] =
reusableDeps[D].map { case (d, rev) =>
ShouldComponentUpdateComponent(rev, () => render(d))
protected[hooks] final case class ReuseComponentProps[A](value: A, render: A => VdomNode)(implicit val reusability: Reusability[A]) {
def renderVdom: VdomNode = render(value)
}

private implicit val reusabilityInstance: Reusability[ReuseComponentProps[Any]] =
Reusability( (a, b) => a.reusability.test(a.value, b.value) )

// Component for reuse. Must be stable.
private val ReuseComponent = React.memo(ScalaFnComponent[ReuseComponentProps[Any]](_.renderVdom))

def shouldComponentUpdate[D](render: D => VdomNode)(implicit r: Reusability[D]): CustomHook[() => D, VdomNode] = {
CustomHook[() => D]
.buildReturning{ deps =>
ReuseComponent(ReuseComponentProps(deps(), render).asInstanceOf[ReuseComponentProps[Any]] )
}
}

lazy val useForceUpdate: CustomHook[Unit, Reusable[DefaultEffects.Sync[Unit]]] = {
Expand Down

0 comments on commit 3c0f6fa

Please sign in to comment.