Skip to content

Commit 7947682

Browse files
committed
More ScalazReact extensions: {state,setState,modState,modStateF}IO.
1 parent 83f8f08 commit 7947682

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

doc/CHANGELOG-0.7.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ https://gist.github.com/japgolly/c68482dbadb0077f550c
88
* Added a router! _(See the `extra` module)_.
99
* Moved `.experiment` into a new module called `extra`.
1010
* More supported React tags and attributes.
11+
* More ScalazReact extensions: `{state,setState,modState,modStateF}IO`.
1112
* Removed deprecated methods marked for removal in 0.7.0.
1213

1314
##### Refs

scalaz-7.0/src/main/scala/japgolly/scalajs/react/ScalazReact.scala

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,9 @@ object ScalazReact extends vdom.ScalazImplicits {
229229
ReactS.zoomU[M, T, A](ev.subst[({type λ[σ] = ReactST[M, σ, A]})#λ](_r))
230230
}
231231

232-
@inline implicit final class SzRExt_CompStateAccessOps[C[_], S](val _c: C[S]) extends AnyVal {
232+
@inline implicit final def toSzRExtCompStateAccessOps[C[_]: CompStateAccess, S](c: C[S]) = new SzRExt_CompStateAccessOps(c)
233+
final class SzRExt_CompStateAccessOps[C[_], S](val _c: C[S]) extends AnyVal {
234+
// CompStateAccess[C] should really be a class param but then we lose the AnyVal
233235
type CC = CompStateAccess[C]
234236

235237
private def run[M[+_], A, B](st: => ReactST[M, S, A], f: (S, S, A, => IO[Unit]) => IO[B])(implicit C: CC, M: M ~> IO): IO[B] =
@@ -249,16 +251,32 @@ object ScalazReact extends vdom.ScalazImplicits {
249251
i => runState(f(i) addCallback cb(i))
250252

251253
def runStateF[M[+_], A](st: => ReactST[M, S, A])(implicit C: CC, M: M ~> IO, F: ChangeFilter[S]): IO[A] =
252-
run[M, A, A](st, (s1,s2,a,io) => if (F.allowChange(s1,s2)) io.map(_ => a) else IO(a))
254+
run[M, A, A](st, (s1,s2,a,io) => F(s1, s2, IO(a), _ => io.map(_ => a)))
253255

254256
def _runStateF[I, M[+_], A](f: I => ReactST[M, S, A])(implicit C: CC, M: M ~> IO, F: ChangeFilter[S]): I => IO[A] =
255257
i => runStateF(f(i))
256258

257259
def _runStateF[I, M[+_], A](f: I => ReactST[M, S, A], cb: I => OpCallbackIO)(implicit C: CC, M: M ~> IO, N: Monad[M], F: ChangeFilter[S]): I => IO[A] =
258260
i => runStateF(f(i) addCallback cb(i))
261+
262+
@inline def stateIO(implicit C: CC): IO[S] =
263+
IO(C state _c)
264+
265+
@inline def setStateIO(s: S, cb: OpCallbackIO = undefined)(implicit C: CC): IO[Unit] =
266+
IO(C.setState(_c, s, cb))
267+
268+
@inline def modStateIO(f: S => S, cb: OpCallbackIO = undefined)(implicit C: CC): IO[Unit] =
269+
IO(_c.modState(f, cb))
270+
271+
def modStateIOF(f: S => S, cb: OpCallbackIO = undefined)(implicit C: CC, F: ChangeFilter[S]): IO[Unit] =
272+
stateIO.flatMap(s1 =>
273+
F(s1, f(s1), IO(()), setStateIO(_, cb)))
259274
}
260275

261-
case class ChangeFilter[S](allowChange: (S, S) => Boolean)
276+
final case class ChangeFilter[S](allowChange: (S, S) => Boolean) {
277+
def apply[A](s1: S, s2: S, orElse: => A, change: S => A): A =
278+
if (allowChange(s1, s2)) change(s2) else orElse
279+
}
262280
object ChangeFilter {
263281
def refl[S] = apply[S](_ != _)
264282
def reflOn[S, T](f: S => T) = apply[S](f(_) != f(_))

scalaz-7.1/src/main/scala/japgolly/scalajs/react/ScalazReact.scala

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ object ScalazReact extends vdom.ScalazImplicits {
233233
ReactS.zoomU[M, T, A](ev.subst[({type λ[σ] = ReactST[M, σ, A]})#λ](_r))
234234
}
235235

236-
@inline implicit final class SzRExt_CompStateAccessOps[C[_], S](val _c: C[S]) extends AnyVal {
236+
@inline implicit final def toSzRExtCompStateAccessOps[C[_]: CompStateAccess, S](c: C[S]) = new SzRExt_CompStateAccessOps(c)
237+
final class SzRExt_CompStateAccessOps[C[_], S](val _c: C[S]) extends AnyVal {
238+
// CompStateAccess[C] should really be a class param but then we lose the AnyVal
237239
type CC = CompStateAccess[C]
238240

239241
private def run[M[_], A, B](st: => ReactST[M, S, A], f: (S, S, A, => IO[Unit]) => IO[B])(implicit C: CC, M: M ~> IO): IO[B] =
@@ -253,16 +255,32 @@ object ScalazReact extends vdom.ScalazImplicits {
253255
i => runState(f(i) addCallback cb(i))
254256

255257
def runStateF[M[_], A](st: => ReactST[M, S, A])(implicit C: CC, M: M ~> IO, F: ChangeFilter[S]): IO[A] =
256-
run[M, A, A](st, (s1,s2,a,io) => if (F.allowChange(s1,s2)) io.map(_ => a) else IO(a))
258+
run[M, A, A](st, (s1,s2,a,io) => F(s1, s2, IO(a), _ => io.map(_ => a)))
257259

258260
def _runStateF[I, M[_], A](f: I => ReactST[M, S, A])(implicit C: CC, M: M ~> IO, F: ChangeFilter[S]): I => IO[A] =
259261
i => runStateF(f(i))
260262

261263
def _runStateF[I, M[_], A](f: I => ReactST[M, S, A], cb: I => OpCallbackIO)(implicit C: CC, M: M ~> IO, N: Monad[M], F: ChangeFilter[S]): I => IO[A] =
262264
i => runStateF(f(i) addCallback cb(i))
265+
266+
@inline def stateIO(implicit C: CC): IO[S] =
267+
IO(C state _c)
268+
269+
@inline def setStateIO(s: S, cb: OpCallbackIO = undefined)(implicit C: CC): IO[Unit] =
270+
IO(C.setState(_c, s, cb))
271+
272+
@inline def modStateIO(f: S => S, cb: OpCallbackIO = undefined)(implicit C: CC): IO[Unit] =
273+
IO(_c.modState(f, cb))
274+
275+
def modStateIOF(f: S => S, cb: OpCallbackIO = undefined)(implicit C: CC, F: ChangeFilter[S]): IO[Unit] =
276+
stateIO.flatMap(s1 =>
277+
F(s1, f(s1), IO(()), setStateIO(_, cb)))
263278
}
264279

265-
case class ChangeFilter[S](allowChange: (S, S) => Boolean)
280+
final case class ChangeFilter[S](allowChange: (S, S) => Boolean) {
281+
def apply[A](s1: S, s2: S, orElse: => A, change: S => A): A =
282+
if (allowChange(s1, s2)) change(s2) else orElse
283+
}
266284
object ChangeFilter {
267285
def refl[S] = apply[S](_ != _)
268286
def reflOn[S, T](f: S => T) = apply[S](f(_) != f(_))

test/src/test/scala/japgolly/scalajs/react/ScalazTest.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@ object ScalazTest extends TestSuite {
2424
trait A
2525
trait B
2626
val c = null.asInstanceOf[ComponentScopeM[Unit, S, Unit]]
27+
type U = Unit
28+
type N = TopNode
2729

2830
val tests = TestSuite {
2931
'inference {
30-
"runState(s.liftS)" - test[StateT[M,S,A] ](s => c.runState(s.liftS) ).expect[IO[A]]
31-
"_runState(f.liftS)" - test[B => StateT[M,S,A]](s => c._runState(s.liftS)).expect[B => IO[A]]
32+
"runState(s.liftS)" - test[StateT[M,S,A] ](s => c.runState(s.liftS) ).expect[IO[A]]
33+
"_runState(f.liftS)" - test[B => StateT[M,S,A] ](s => c._runState(s.liftS)).expect[B => IO[A]]
34+
"BackendScope ops" - test[BackendScope[Unit, S] ](_.modStateIO(identity) ).expect[IO[Unit]]
35+
"ComponentScopeM ops" - test[ComponentScopeM[U, S, U] ](_.modStateIO(identity) ).expect[IO[Unit]]
36+
"ReactComponentM ops" - test[ReactComponentM[U, S, U, N]](_.modStateIO(identity) ).expect[IO[Unit]]
3237
}
3338
'runState {
3439
val c = ReactTestUtils.renderIntoDocument(CoreTest.SI())

0 commit comments

Comments
 (0)