Skip to content

Commit 3c0f6fa

Browse files
authored
Merge pull request #1089 from japgolly/usememo-reuse
Reusability in functional components via React.memo instead of class component
2 parents 9e5ab69 + 8ec42ef commit 3c0f6fa

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

library/coreGeneric/src/main/scala/japgolly/scalajs/react/hooks/CustomHook.scala

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package japgolly.scalajs.react.hooks
22

33
import japgolly.microlibs.types.NaturalComposition
4-
import japgolly.scalajs.react.internal.ShouldComponentUpdateComponent
4+
import japgolly.scalajs.react.internal.CoreGeneral.ScalaFnComponent
55
import japgolly.scalajs.react.util.DefaultEffects
66
import japgolly.scalajs.react.vdom.VdomNode
7-
import japgolly.scalajs.react.{PropsChildren, Reusability, Reusable}
7+
import japgolly.scalajs.react.{PropsChildren, React, Reusability, Reusable}
88

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

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

209-
def shouldComponentUpdate[D](render: D => VdomNode)(implicit r: Reusability[D]): CustomHook[() => D, VdomNode] =
210-
reusableDeps[D].map { case (d, rev) =>
211-
ShouldComponentUpdateComponent(rev, () => render(d))
209+
protected[hooks] final case class ReuseComponentProps[A](value: A, render: A => VdomNode)(implicit val reusability: Reusability[A]) {
210+
def renderVdom: VdomNode = render(value)
211+
}
212+
213+
private implicit val reusabilityInstance: Reusability[ReuseComponentProps[Any]] =
214+
Reusability( (a, b) => a.reusability.test(a.value, b.value) )
215+
216+
// Component for reuse. Must be stable.
217+
private val ReuseComponent = React.memo(ScalaFnComponent[ReuseComponentProps[Any]](_.renderVdom))
218+
219+
def shouldComponentUpdate[D](render: D => VdomNode)(implicit r: Reusability[D]): CustomHook[() => D, VdomNode] = {
220+
CustomHook[() => D]
221+
.buildReturning{ deps =>
222+
ReuseComponent(ReuseComponentProps(deps(), render).asInstanceOf[ReuseComponentProps[Any]] )
223+
}
212224
}
213225

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

0 commit comments

Comments
 (0)