fritz2
fritz2 copied to clipboard
Reconsider `RootStore` update behavior
Current behavior
Currently, a RootStore
's value is only updated (i.e. data
flow emits a new value) if the Store receives a new value.
If the Store receives a value that is equal to the current value, no value is emitted.
This is due to the fact that a MutableStateFlow
is used to keep track of the current value which is explicitly designed to behave this way.
Why this is problematic
Imagine a Lens
that is used to strip illegal characters from an input (e.g. characters from a phone number). The expected behavior would be like this:
- Add invalid characters to an input field with a valid input
- Invalid characters get stripped by the Lens
- The store is updated
- The formatting Lens passes the sanitized value upstream to the input
- The input field is updated to have the sanitized value
Instead, the following happens:
- Add invalid characters to an input field with a valid input
- Invalid characters get stripped by the Lens
- The store is not updated since the sanitized input is the same as the current value
- Nothing is passed upstream
- The input field keeps the illegal input
Example code
val allowedCharacters = "abc".toCharArray().toSet()
val sanitizingLens: Lens<String, String> = lensOf(
format = { it },
parse = { it.filter { c -> c in allowedCharacters } }
)
val store = storeOf("").map(sanitizingLens)
div("space-y-4") {
input {
type("text")
}.changes.values() handledBy store.update
p {
store.data.renderText(into = this)
}
}
Proposal
Consider one of the following options:
- Introduce a flag to explictly update the Store's data on any new input
- Change the Store's default behavior to always emit a new value, regardless of the equality of the input