Skip to content

Commit

Permalink
Update documentation for flow id
Browse files Browse the repository at this point in the history
  • Loading branch information
eliekarouz committed Aug 11, 2023
1 parent d90e049 commit 0bded52
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Here's an example of a phone registration code where the user enters their phone

```kotlin
val phoneNumberRegistrationFlow = Flow<Unit, State, Event, Unit, Any>(
id = "PhoneNumberRegistrationFlow",
initialState = {
...
},
Expand Down
55 changes: 55 additions & 0 deletions docs/src/orchid/resources/wiki/reference/flow/FlowId.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: Flow Id
category: Flow
order: 4
---

### Setting Flow Identifiers

When initiating a Flow, it's essential to designate an identifier id for the Flow. This identifier
can be a constant value or dynamically generated based on input.

```kotlin
Flow(
id = "MyFlowFixedId",
// ...
)

Flow(
id = { input -> "MyFlowFor-${input.itemKey}" },
// ...
)
```

### Ensuring Uniqueness

When applying identifiers to your flows, it's not only important to aim for a reasonable level of
uniqueness, but it's also critical to ensure **complete uniqueness** within the specific context of
the `render` block. This consideration becomes particularly significant when dealing with the
initiation of multiple child flows.

In scenarios where you find yourself simultaneously initiating multiple child flows using
the `context.renderChild(input, ChildFlow, ...)` function, it becomes paramount that each flow
instance possesses an identifier that is distinct from all others. This distinction is necessary to
prevent collisions and unexpected interactions between running flows.

The `renderChild` process begins by computing the identifier of the child flow based on the provided
input. Subsequently, this identifier plays a crucial role in determining whether a specific child
flow needs to be newly initiated or resumed from a prior state within the same render block. The
decision is made based on whether the computed identifier matches any previously initiated flows
within the current rendering context. A new flow instance is only created if the computed identifier
differs from those encountered so far.

### Practical Use of Unique IDs for Each Input

Consider an example involving an `ItemsListFlow` and `ItemDetailFlow`. The `ItemsListFlow` maintains
a state variable called `showingDetailsItemKey: String?`. When this variable isn't null, the render
block triggers the `ItemDetailFlow`.

While a fixed ID works well on mobiles, envision a tablet's split-screen layout. Here's where the
challenge arises. The `ItemDetailFlow` remains active, but as you select new items, it needs to
restart. Using a fixed ID for `ItemDetailFlow` causes the initial flow to resume, preventing new
starts.

The remedy? Incorporate the `itemKey` into the Flow's ID. This guarantees a fresh flow for each
item, ensuring that selecting a different item leads to a new flow initiation.
1 change: 1 addition & 0 deletions docs/src/orchid/resources/wiki/reference/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
1. [Hierarchical Flows](flow/HierarchicalFlows.md)
2. [Feedback Loops](flow/FeedbackLoops.md)
3. [Starting Flows](flow/StartingFlows.md)
4. [Flow Id](flow/FlowId.md)

### Rendering

Expand Down
1 change: 1 addition & 0 deletions docs/src/orchid/resources/wiki/tutorials/ARootFlow.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ sealed class Event {
}

val TutorialsFlow = Flow<Unit, State, Event, Nothing, Any>(
id = "TutorialsFlow",
initialState = { State() },
stepper = { state, event ->
when (event) {
Expand Down
3 changes: 2 additions & 1 deletion docs/src/orchid/resources/wiki/tutorials/Counter.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ import com.feedbacktree.flow.core.Flow
import com.feedbacktree.flow.core.advance

val CounterFlow = Flow<Unit, State, Event, Nothing, CounterScreen>( // 1
initialState = { State(counter = 0) }, // 2
id = "CounterFlow",
initialState = { State(counter = 0) }, // 2
stepper = { state, event -> // 3
when (event) {
Event.Increment -> state.copy(
Expand Down
1 change: 1 addition & 0 deletions docs/src/orchid/resources/wiki/tutorials/Login.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.feedbacktree.flow.core.*
import io.reactivex.Observable

val LoginFlow = Flow<String, State, Event, Unit, LoginScreen>( // 1
id = "LoginFlow",
initialState = { lastEmailUsed -> State(email = lastEmailUsed) }, // 2
stepper = { state, event ->
when (event) {
Expand Down

0 comments on commit 0bded52

Please sign in to comment.