Skip to content

Commit bca16d2

Browse files
committed
Revise hooks methods with deps
1 parent d061ec9 commit bca16d2

File tree

7 files changed

+85
-69
lines changed

7 files changed

+85
-69
lines changed

coreGeneric/src/main/scala/japgolly/scalajs/react/hooks/Api.scala

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ object Api {
126126
*
127127
* @see https://reactjs.org/docs/hooks-reference.html#usecallback
128128
*/
129-
final def useCallbackWithDeps[A, D](callback: => A, deps: => D)(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
130-
useCallbackWithDepsBy(_ => callback, _ => deps)
129+
final def useCallbackWithDeps[D, A](deps: => D)(callback: D => A)(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
130+
useCallbackWithDepsBy(_ => deps)(_ => callback)
131131

132132
/** Returns a memoized callback.
133133
*
@@ -137,8 +137,8 @@ object Api {
137137
*
138138
* @see https://reactjs.org/docs/hooks-reference.html#usecallback
139139
*/
140-
final def useCallbackWithDepsBy[A, D](callback: Ctx => A, deps: Ctx => D)(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
141-
customBy(ctx => UseCallback(callback(ctx), deps(ctx)))
140+
final def useCallbackWithDepsBy[D, A](deps: Ctx => D)(callback: Ctx => D => A)(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
141+
customBy(ctx => UseCallback.withDeps(deps(ctx))(callback(ctx)))
142142

143143
/** Accepts a context object and returns the current context value for that context. The current context value is
144144
* determined by the value prop of the nearest `<MyContext.Provider>` above the calling component in the tree.
@@ -243,8 +243,8 @@ object Api {
243243
*
244244
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
245245
*/
246-
final def useEffectWithDeps[A, D](effect: A, deps: => D)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
247-
custom(ReusableEffect.useEffect(effect, deps))
246+
final def useEffectWithDeps[D, A](deps: => D)(effect: D => A)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
247+
custom(ReusableEffect.useEffect(deps)(effect))
248248

249249
/** The callback passed to useEffect will run after the render is committed to the screen. Think of effects as an
250250
* escape hatch from React’s purely functional world into the imperative world.
@@ -253,8 +253,8 @@ object Api {
253253
*
254254
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
255255
*/
256-
final def useEffectWithDepsBy[A, D](effect: Ctx => A, deps: Ctx => D)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
257-
customBy(ctx => ReusableEffect.useEffect(effect(ctx), deps(ctx)))
256+
final def useEffectWithDepsBy[D, A](deps: Ctx => D)(effect: Ctx => D => A)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
257+
customBy(ctx => ReusableEffect.useEffect(deps(ctx))(effect(ctx)))
258258

259259
/** When invoked, forces a re-render of your component. */
260260
final def useForceUpdate(implicit step: Step): step.Next[Reusable[DefaultEffects.Sync[Unit]]] =
@@ -326,8 +326,8 @@ object Api {
326326
*
327327
* @see https://reactjs.org/docs/hooks-reference.html#useLayoutEffect
328328
*/
329-
final def useLayoutEffectWithDeps[A, D](effect: A, deps: => D)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
330-
custom(ReusableEffect.useLayoutEffect(effect, deps))
329+
final def useLayoutEffectWithDeps[D, A](deps: => D)(effect: D => A)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
330+
custom(ReusableEffect.useLayoutEffect(deps)(effect))
331331

332332
/** The signature is identical to [[useEffect]], but it fires synchronously after all DOM mutations. Use this to
333333
* read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed
@@ -339,8 +339,8 @@ object Api {
339339
*
340340
* @see https://reactjs.org/docs/hooks-reference.html#useLayoutEffect
341341
*/
342-
final def useLayoutEffectWithDepsBy[A, D](effect: Ctx => A, deps: Ctx => D)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
343-
customBy(ctx => ReusableEffect.useLayoutEffect(effect(ctx), deps(ctx)))
342+
final def useLayoutEffectWithDepsBy[D, A](deps: Ctx => D)(effect: Ctx => D => A)(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
343+
customBy(ctx => ReusableEffect.useLayoutEffect(deps(ctx))(effect(ctx)))
344344

345345
/** Returns a memoized value.
346346
*
@@ -352,8 +352,8 @@ object Api {
352352
*
353353
* @see https://reactjs.org/docs/hooks-reference.html#usememo
354354
*/
355-
final def useMemo[A, D](create: => A, deps: => D)(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
356-
useMemoBy(_ => create, _ => deps)
355+
final def useMemo[D, A](deps: => D)(create: D => A)(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
356+
useMemoBy(_ => deps)(_ => create)
357357

358358
/** Returns a memoized value.
359359
*
@@ -365,8 +365,8 @@ object Api {
365365
*
366366
* @see https://reactjs.org/docs/hooks-reference.html#usememo
367367
*/
368-
final def useMemoBy[A, D](create: Ctx => A, deps: Ctx => D)(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
369-
customBy(ctx => UseMemo(create(ctx), deps(ctx)))
368+
final def useMemoBy[D, A](deps: Ctx => D)(create: Ctx => D => A)(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
369+
customBy(ctx => UseMemo(deps(ctx))(create(ctx)))
370370

371371
/** An alternative to [[useState]]. Accepts a reducer of type `(state, action) => newState`, and returns the
372372
* current state paired with a dispatch method.
@@ -521,8 +521,8 @@ object Api {
521521
*
522522
* @see https://reactjs.org/docs/hooks-reference.html#usecallback
523523
*/
524-
final def useCallbackWithDepsBy[A, D](callback: CtxFn[A], deps: CtxFn[D])(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
525-
useCallbackWithDepsBy(step.squash(callback)(_), step.squash(deps)(_))
524+
final def useCallbackWithDepsBy[D, A](deps: CtxFn[D])(callback: CtxFn[D => A])(implicit a: UseCallbackArg[A], r: Reusability[D], step: Step): step.Next[Reusable[A]] =
525+
useCallbackWithDepsBy(step.squash(deps)(_))(step.squash(callback)(_))
526526

527527
/** Accepts a context object and returns the current context value for that context. The current context value is
528528
* determined by the value prop of the nearest `<MyContext.Provider>` above the calling component in the tree.
@@ -569,8 +569,8 @@ object Api {
569569
*
570570
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
571571
*/
572-
final def useEffectWithDepsBy[A, D](effect: CtxFn[A], deps: CtxFn[D])(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
573-
useEffectWithDepsBy(step.squash(effect)(_), step.squash(deps)(_))
572+
final def useEffectWithDepsBy[D, A](deps: CtxFn[D])(effect: CtxFn[D => A])(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
573+
useEffectWithDepsBy(step.squash(deps)(_))(step.squash(effect)(_))
574574

575575
/** The callback passed to useEffect will run after the render is committed to the screen. Think of effects as an
576576
* escape hatch from React’s purely functional world into the imperative world.
@@ -607,8 +607,8 @@ object Api {
607607
*
608608
* @see https://reactjs.org/docs/hooks-reference.html#useLayoutEffect
609609
*/
610-
final def useLayoutEffectWithDepsBy[A, D](effect: CtxFn[A], deps: CtxFn[D])(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
611-
useLayoutEffectWithDepsBy(step.squash(effect)(_), step.squash(deps)(_))
610+
final def useLayoutEffectWithDepsBy[D, A](deps: CtxFn[D])(effect: CtxFn[D => A])(implicit a: UseEffectArg[A], r: Reusability[D], step: Step): step.Self =
611+
useLayoutEffectWithDepsBy(step.squash(deps)(_))(step.squash(effect)(_))
612612

613613
/** The signature is identical to [[useEffect]], but it fires synchronously after all DOM mutations. Use this to
614614
* read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed
@@ -633,8 +633,8 @@ object Api {
633633
*
634634
* @see https://reactjs.org/docs/hooks-reference.html#usememo
635635
*/
636-
final def useMemoBy[A, D](create: CtxFn[A], deps: CtxFn[D])(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
637-
useMemoBy(step.squash(create)(_), step.squash(deps)(_))
636+
final def useMemoBy[D, A](deps: CtxFn[D])(create: CtxFn[D => A])(implicit r: Reusability[D], step: Step): step.Next[Reusable[A]] =
637+
useMemoBy(step.squash(deps)(_))(step.squash(create)(_))
638638

639639
/** An alternative to [[useState]]. Accepts a reducer of type `(state, action) => newState`, and returns the
640640
* current state paired with a dispatch method.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ object CustomHook {
190190
}
191191
}
192192

193-
def reusableByDeps[A, D](create: (D, Int) => A)(implicit r: Reusability[D]): CustomHook[() => D, Reusable[A]] =
193+
def reusableByDeps[D, A](create: (D, Int) => A)(implicit r: Reusability[D]): CustomHook[() => D, Reusable[A]] =
194194
reusableDeps[D].map { case (d, rev) => Reusable.implicitly(rev).withValue(create(d, rev)) }
195195

196196
def shouldComponentUpdate[D](render: D => VdomNode)(implicit r: Reusability[D]): CustomHook[() => D, VdomNode] =

coreGeneric/src/main/scala/japgolly/scalajs/react/hooks/Hooks.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ object Hooks {
4343
def apply[A](callback: => A)(implicit a: UseCallbackArg[A]): CustomHook[Unit, Reusable[A]] =
4444
CustomHook.delay(create(callback, new js.Array[Any]))
4545

46-
def apply[A, D](callback: => A, deps: => D)(implicit a: UseCallbackArg[A], r: Reusability[D]): CustomHook[Unit, Reusable[A]] =
46+
def withDeps[D, A](deps: => D)(callback: D => A)(implicit a: UseCallbackArg[A], r: Reusability[D]): CustomHook[Unit, Reusable[A]] =
4747
CustomHook.reusableDeps[D]
4848
.apply(() => deps)
49-
.map(rev => create(callback, js.Array[Any](rev)))
49+
.map { case (d, rev) => create(callback(d), js.Array[Int](rev)) }
5050
}
5151

5252
// ===================================================================================================================
@@ -102,22 +102,22 @@ object Hooks {
102102

103103
object ReusableEffect {
104104

105-
def useEffect[A, D](effect: => A, deps: => D)(implicit a: UseEffectArg[A], r: Reusability[D]): CustomHook[Unit, Unit] =
105+
def useEffect[D, A](deps: => D)(effect: D => A)(implicit a: UseEffectArg[A], r: Reusability[D]): CustomHook[Unit, Unit] =
106106
CustomHook.reusableDeps[D]
107107
.apply(() => deps)
108-
.map(rev => facade.React.useEffect(a.toJs(effect), js.Array[Any](rev)))
108+
.map { case (d, rev) => facade.React.useEffect(a.toJs(effect(d)), js.Array[Int](rev)) }
109109

110-
def useLayoutEffect[A, D](effect: => A, deps: => D)(implicit a: UseEffectArg[A], r: Reusability[D]): CustomHook[Unit, Unit] =
110+
def useLayoutEffect[D, A](deps: => D)(effect: D => A)(implicit a: UseEffectArg[A], r: Reusability[D]): CustomHook[Unit, Unit] =
111111
CustomHook.reusableDeps[D]
112112
.apply(() => deps)
113-
.map(rev => facade.React.useLayoutEffect(a.toJs(effect), js.Array[Any](rev)))
113+
.map { case (d, rev) => facade.React.useLayoutEffect(a.toJs(effect(d)), js.Array[Int](rev)) }
114114
}
115115

116116
// ===================================================================================================================
117117

118118
object UseMemo {
119-
def apply[A, D](create: => A, deps: => D)(implicit r: Reusability[D]): CustomHook[Unit, Reusable[A]] =
120-
CustomHook.reusableByDeps[A, D] { case (_, rev) => facade.React.useMemo(() => create, js.Array[Any](rev: Int)) }
119+
def apply[D, A](deps: => D)(create: D => A)(implicit r: Reusability[D]): CustomHook[Unit, Reusable[A]] =
120+
CustomHook.reusableByDeps[D, A] { case (d, rev) => facade.React.useMemo(() => create(d), js.Array[Int](rev)) }
121121
.apply(() => deps)
122122
}
123123

doc/HOOKS.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,21 @@ object Example {
172172
| JavaScript | scalajs-react |
173173
| --------- | -------- |
174174
| `useCallback(c)` | `.useCallback(c)` |
175-
| `useCallback(c, [deps])` | `.useCallbackWithDeps(c, (deps))` |
175+
| `useCallback(c, [deps])` | `.useCallbackWithDeps((deps))(_ => c)` |
176+
| `useCallback(f([deps]), [deps])` | `.useCallbackWithDeps((deps))(f)` |
176177
| `useContext(c)` | `.useContext(c)` |
177178
| `useDebugValue(desc)` | `.useDebugValue(desc)` |
178179
| `useDebugValue(a, f)` | `.useDebugValue(f(a))` |
179180
| `useEffect(e)` | `.useEffect(e)` |
180181
| `useEffect(e, [])` | `.useEffectOnMount(e)` |
181-
| `useEffect(e, [deps])` | `.useEffectWithDeps(e, (deps))` |
182+
| `useEffect(e, [deps])` | `.useEffectWithDeps((deps))(_ => e)` |
183+
| `useEffect(f([deps]), [deps])` | `.useEffectWithDeps((deps))(f)` |
182184
| `useLayoutEffect(e)` | `.useLayoutEffect(e)` |
183185
| `useLayoutEffect(e, [])` | `.useLayoutEffectOnMount(e)` |
184-
| `useLayoutEffect(e, [deps])` | `.useLayoutEffectWithDeps(e, (deps))` |
185-
| `useMemo(() => a, [deps])` | `.useMemo(a, (deps))` |
186+
| `useLayoutEffect(e, [deps])` | `.useLayoutEffectWithDeps((deps))(_ => e)` |
187+
| `useLayoutEffect(f([deps]), [deps])` | `.useLayoutEffectWithDeps((deps))(f)` |
188+
| `useMemo(() => a, [deps])` | `.useMemo((deps))(_ => a) |
189+
| `useMemo(() => f([deps]), [deps])` | `.useMemo((deps))(f) |
186190
| `useReducer(f, s)` | `.useReducer(f, s)` |
187191
| `useReducer(f, a, i)` | `.useReducer(f, i(a))`<br>*(Note: `i(a)` is actually `(=> i(a))` and isn't evaluated immediately)* |
188192
| `useRef()` | `.useRefToAnyVdom` <br> `.useRefToVdom[DomType]` <br> `.useRefToScalaComponent(component)` <br> `.useRefToScalaComponent[P, S, B]` <br> `.useRefToJsComponent(component)` <br> `.useRefToJsComponent[P, S]` <br> `.useRefToJsComponentWithMountedFacade[P, S, F]` |

doc/changelog/2.0.0.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Contents:
1111
- [Changes: Backwards-Compatible](#changes-backwards-compatible)
1212
- [Changes: Auto-Migratable](#changes-auto-migratable)
1313
- [Migration](#migration)
14+
- [Changes in RC2](#changes-in-rc2)
1415
- [Thanks](#thanks)
1516

1617

@@ -306,6 +307,17 @@ You can run the script in the Migration section at the bottom of the page to aut
306307
```
307308

308309

310+
# Changes in RC2
311+
312+
* Bugfix in the `useCallbackWithDeps{,By}` hook
313+
* Changed the pattern in hook signatures from `(mainArg: => A, deps: => D)` to `(deps: D)(mainArg: D => A)`.
314+
Affected methods:
315+
* `useCallbackWithDeps{,By}`
316+
* `useEffectWithDeps{,By}`
317+
* `useLayoutEffectWithDeps{,By}`
318+
* `useMemo{,By}`
319+
320+
309321
# Thanks
310322

311323
A lot of this was kindly sponsored by [Gemini](https://www.gemini.edu/)/[NOIRLab](https://nationalastro.org/)/[AURA](https://www.aura-astronomy.org/).

facadeMain/src/main/scala/japgolly/scalajs/react/facade/Hooks.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import scala.scalajs.js.|
1212
@nowarn("cat=unused")
1313
trait Hooks extends js.Object {
1414

15-
final type HookDeps = js.UndefOr[js.Array[Any]] | Null
15+
final type HookDeps = js.UndefOr[js.Array[_]] | Null
1616

1717
final type UseStateSetter[S] = js.Function1[S | js.Function1[S, S], Unit]
1818
final type UseState[S] = js.Tuple2[S, UseStateSetter[S]]

0 commit comments

Comments
 (0)