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 One and Done entry was bad advice, or at least incomplete. Updated to describe the Skippable Workflow pattern we've been using with a lot of success lately.
Copy file name to clipboardExpand all lines: docs/userguide/common-patterns.md
+49-3Lines changed: 49 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -34,15 +34,61 @@ simply by rendering various children. It may just combine the renderings of mult
34
34
use its props to determine which of a set of children to render. Such workflows can often be
35
35
stateless.
36
36
37
-
## One-and-done Workflows (RenderingT v. OutputT)
37
+
## Skippable Workflows
38
38
39
-
A common question is “why can’t I emit output from `initialState`,” or “what if my Workflow realizes it doesn’t actually need to run? The most efficient, and most expressive, way to handle this is to use an optional or conditional `Rendering` type, and an `Output` of [`Never`](https://nshipster.com/never/)/[`Nothing`](https://medium.com/@agrawalsuneet/the-nothing-type-kotlin-2e7df43b0111).
39
+
* Why can’t I emit output from `initialState`?
40
+
* Why can’t I emit output from `render`?
41
+
* Why can't I change states during `render`?
42
+
* What if while rendering my Workflow realizes it doesn’t actually need to run?
43
+
44
+
The best pattern we've found for all of these situations is a "skippable workflow".
45
+
The idea is that a workflow that performs work that may not actually be necessary
46
+
provides an extra function for parents to call.
47
+
The parent can call this during the upstream action
48
+
where it's deciding whether or not to enter the state
49
+
in which the child would be run.
50
+
51
+
Perhaps it's a simple boolean function indicating whether or not the child actually has any work to do:
52
+
53
+
```kotlin
54
+
state =if (stepTwoWorkflow.isThisNecessary()) RunStepTwoelseRunStepThree
55
+
```
56
+
57
+
Perhaps it can return the usual output, or null to indicate that async work is required:
58
+
59
+
```kotlin
60
+
state = stepTwoWorkflow.instantResponse(stepTwoInput)?.let { RunStepThree(it) }
61
+
?:RunStepTwo
62
+
```
63
+
64
+
A particularly nice aspect of this approach is how it keeps
65
+
the knowledge encapsulated by the skippable workflow from leaking.
66
+
67
+
Any hacks you might resort during `initialState` or `render`
68
+
to make it seem like a workflow is short circuiting are big smells.
69
+
They are guaranteed to cause performance problems that compound,
70
+
and add needless complexity.
71
+
72
+
## Optional renderings (using RenderT instead of OutputT)
73
+
74
+
Besides the [skippable workflow](#skippable-workflows) pattern described above,
75
+
another way a child can communicate to its parent that it has no work to do
76
+
is with a nullable or otherwise un-renderable rendering type.
77
+
(If you're using this patt
78
+
and .
40
79
41
80
Imagine a `PromptForPermissionMaybeWorkflow`, that renders a UI to get a passcode, but only if that permission has not already been granted. If you make its `RenderingT` nullable (e.g. `Screen?`), it can return `null` to indicate that its job is done. Its callers will be synchronously informed that the coast is clear, and can immediately render what they actually care about.
42
81
43
82
Another variation of this pattern is to use a sealed class / enum type for `Rendering`, with a `Working` type that implements `Screen`, and a unviewable `Finished` type that carries the work product.
44
83
45
-
A good rule of thumb for choosing between using `Rendering` or `Output` is to remember that `Output` is event-like, and is always asynchronous. A parent waiting for an output must be given something to render in the meantime. Using `Rendering` is a great idiom for a one-and-done workflow tasked with providing a single product, especially one that might be available instantly.
84
+
Either way, it's a good idea to use an an output type of
0 commit comments