Skip to content

Commit ad47a42

Browse files
committed
Support CallbackOption[Unit] being passed directly to event handling vdom
Closes #957
1 parent 71fb6e9 commit ad47a42

File tree

5 files changed

+43
-10
lines changed

5 files changed

+43
-10
lines changed

callback/src/main/scala/japgolly/scalajs/react/util/EffectCallback.scala

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import japgolly.scalajs.react.callback._
44
import scala.scalajs.js
55

66
abstract class EffectFallbacks1 extends EffectFallbacks2 {
7-
implicit def callback : Effect.Sync [CallbackTo ] = EffectCallback.callback
8-
implicit def asyncCallback: Effect.Async[AsyncCallback] = EffectCallback.asyncCallback
7+
implicit def callback : Effect.Sync [CallbackTo ] = EffectCallback.callback
8+
implicit def callbackOption: Effect.Dispatch[CallbackOption] = EffectCallback.callbackOption
9+
implicit def asyncCallback : Effect.Async [AsyncCallback ] = EffectCallback.asyncCallback
910
}
1011

1112
object EffectCallback {
@@ -82,6 +83,29 @@ object EffectCallback {
8283

8384
// ===================================================================================================================
8485

86+
object callbackOption extends Dispatch[CallbackOption] {
87+
88+
override def delay[A](a: => A): CallbackOption[A] =
89+
CallbackOption.delay(a)
90+
91+
override def pure[A](a: A): CallbackOption[A] =
92+
CallbackOption.pure(a)
93+
94+
override def map[A, B](fa: CallbackOption[A])(f: A => B): CallbackOption[B] =
95+
fa map f
96+
97+
override def flatMap[A, B](fa: CallbackOption[A])(f: A => CallbackOption[B]): CallbackOption[B] =
98+
fa flatMap f
99+
100+
override def dispatch[A](fa: CallbackOption[A]): Unit =
101+
fa.asCallback.void
102+
103+
override def dispatchFn[A](fa: => CallbackOption[A]): js.Function0[Unit] =
104+
() => {fa.underlyingRepr(); ()}
105+
}
106+
107+
// ===================================================================================================================
108+
85109
object asyncCallback extends Async[AsyncCallback] with Dispatch.WithDefaults[AsyncCallback] {
86110
@inline override def delay[A](a: => A) =
87111
AsyncCallback.delay(a)

coreGeneric/src/main/scala-2/japgolly/scalajs/react/vdom/Attr.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,21 @@ object Attr {
6464
}
6565

6666
trait EventCallback0 {
67-
implicit def sync[F[_]](implicit F: Dispatch[F]): EventCallback[F[Unit]] =
67+
implicit def dispatch[F[_]](implicit F: Dispatch[F]): EventCallback[F[Unit]] =
6868
new EventCallback(fa => F.dispatchFn(fa))
6969

70-
implicit def reusableSync[F[_]](implicit F: Dispatch[F]): EventCallback[Reusable[F[Unit]]] =
70+
implicit def reusableDispatch[F[_]](implicit F: Dispatch[F]): EventCallback[Reusable[F[Unit]]] =
7171
new EventCallback(fa => F.dispatchFn(fa))
7272
}
7373

7474
object EventCallback extends EventCallback0 {
7575
import DefaultEffects.{Sync => D}
7676

7777
implicit val defaultSync: EventCallback[D[Unit]] =
78-
sync(D)
78+
dispatch(D)
7979

8080
implicit lazy val reusableDefaultSync: EventCallback[Reusable[D[Unit]]] =
81-
reusableSync(D)
81+
reusableDispatch(D)
8282
}
8383

8484
type EventHandler[E[+x <: dom.Node] <: facade.SyntheticEvent[x]] =

coreGeneric/src/main/scala-3/japgolly/scalajs/react/vdom/Attr.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,21 @@ object Attr {
8080
}
8181

8282
trait EventCallback0 {
83-
implicit def sync[F[_]](implicit F: Dispatch[F]): EventCallback[F[Unit]] =
83+
implicit def dispatch[F[_]](implicit F: Dispatch[F]): EventCallback[F[Unit]] =
8484
new EventCallback(fa => F.dispatchFn(fa))
8585

86-
implicit def reusableSync[F[_]](implicit F: Dispatch[F]): EventCallback[Reusable[F[Unit]]] =
86+
implicit def reusableDispatch[F[_]](implicit F: Dispatch[F]): EventCallback[Reusable[F[Unit]]] =
8787
new EventCallback(fa => F.dispatchFn(fa))
8888
}
8989

9090
object EventCallback extends EventCallback0 {
9191
import DefaultEffects.{Sync => D}
9292

9393
implicit val defaultSync: EventCallback[D[Unit]] =
94-
sync(D)
94+
dispatch(D)
9595

9696
implicit lazy val reusableDefaultSync: EventCallback[Reusable[D[Unit]]] =
97-
reusableSync(D)
97+
reusableDispatch(D)
9898
}
9999

100100
type EventHandler[E[+x <: dom.Node] <: facade.SyntheticEvent[x]] =

doc/changelog/2.0.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ You can run the script in the Migration section at the bottom of the page to aut
337337
* `TriStateCheckbox`'s `onKeyDown` handler was calling `event.preventDefault()` on unhandled keys
338338
* Fix the Scala 3 version of `renderBackend` to support polymorphic backends
339339
*(e.g. `renderBackend[Backend[X]]` where `X` is a type already in scope)*
340+
* Support `CallbackOption[Unit]` being passed directly to event handling vdom
340341
341342
* `TriStateCheckbox` now accepts an optional `Reusable[TagMod]` in its `Props` that will be applied to the `<input>`
342343

tests/src/test/scala/japgolly/scalajs/react/core/vdom/VdomTest.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,13 @@ object VdomTest extends TestSuite {
153153
}
154154
}
155155

156+
"callbackOption" - {
157+
"value" - assertCompiles(^.onKeyDown --> CallbackOption.pass)
158+
"fn" - {
159+
def keys(e: ReactKeyboardEventFromHtml): CallbackOption[Unit] = ???
160+
assertCompiles(^.onKeyDown ==> keys)
161+
}
162+
}
163+
156164
}
157165
}

0 commit comments

Comments
 (0)