You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `Callback` class encapsulates logic and side-effects that are meant to be *executable by React*, when/if React chooses to execute it. Examples are React responding to the user clicking a button, or React unmounting a component.
5
+
6
+
**WARNING**: If you're new to scalajs-react and typed effects (or just functional programming in general), then it's important you read this because if you incorrectly mix this with imperative-style code that performs side-effects, you'll likely have runtime bugs where data goes stale and/or changes go undetected.
7
+
8
+
#### Contents
9
+
-[Introduction](#introduction)
10
+
-[Utilities once you have a `Callback`](#utilities-once-you-have-a-callback)
Once you have a `Callback` you can run it manually if you need, by calling `.runNow()`.
59
-
It isn't necessary and you shouldn't do it because scalajs-react handles it for you to ensure things run at the right time
60
-
on the right threads, but if you ever want to, you can.
95
+
Composition
96
+
===========
61
97
62
-
#### Fusion via `>>`
98
+
When you want to compose multiple `Callback` instances, there are many ways depending on what specifically you want to do.
99
+
**(Most-common)*`.flatMap` and/or for-comprehensions. Same as using Scala's `Future`.
100
+
**(Most-common)*`>>`. This operator composes callbacks sequentially. i.e. `a >> b >> c` will create a new callback which will execute `a` first, then `b` second, and finally `c` third.
101
+
* If you want to compose more than two callbacks, or don't know how many you'll have at runtime, there is `Callback.sequence` and `Callback.traverse`.
102
+
* Monadic and applicative ops that'd you'd expect coming from languages like Haskell are there (`*>`, `<*`, `>>`, `<<`, `>>=`, etc). They're baked in rather than typeclass-provided.
63
103
64
104
The `>>` operator deserves a special mention as it's commonly useful.
65
105
It's used to fuse to callbacks together sequentially.
66
-
It's like a pure version of `;` which is how you sequence statements imperatively.
106
+
It's like a pure version of `;` which is how you sequence statements imperatively (i.e. `doThis(); doThat()` becomes `doThis >> doThat`).
67
107
68
108
```scala
69
109
defgreet:Callback=
@@ -87,6 +127,15 @@ def greet: Callback = {
87
127
valbye=Callback(println("Goodbye."))
88
128
hello.flatMap(_ => bye)
89
129
}
130
+
131
+
// and again, equivalent to this ↓
132
+
133
+
defgreet:Callback=
134
+
for {
135
+
_ <-Callback(println("Hello."))
136
+
_ <-Callback(println("Goodbye."))
137
+
} yield ()
138
+
}
90
139
```
91
140
92
141
If you're wondering why `>>`, it's a convention used in various other monadic libraries.
@@ -170,3 +219,20 @@ Notice that we change `speak()` into `speak` as it's now pure.
170
219
It's actually recommended that you *not* take this approach and instead, use proper operators to combine callbacks as the compiler will be able to offer help and catch problems.
171
220
172
221
222
+
Manual Execution
223
+
================
224
+
225
+
As is stressed above, `Callback`s are meant to be executed by React at a time and frequency of its choosing.
226
+
227
+
There are scenarios in which you may want to execute a callback manually:
228
+
* Working with an external service.
229
+
* In an AJAX callback.
230
+
* In a websocket callback.
231
+
* In a unit test.
232
+
233
+
There are two ways to go about this:
234
+
235
+
1. Execute the `Callback` yourself by calling `.runNow()`.
236
+
2. Ask `scalajs-react` for an interface that performs the side-effects directly instead of returning `Callback`s. See https://japgolly.github.io/scalajs-react/#examples/websockets for a demo.
237
+
238
+
Reminder: You should never do this in a React context.
0 commit comments