*How high should I hoist the value property of a `...
# compose
j
How high should I hoist the value property of a
BasicTextFiled
?
More details in đź§µ
Example 1:
Copy code
var myString by mutableStateOf("")
BasicTextField(
  value = myString,
  onValueChange = { 
    myString = it
  }
)
Everything works fine here. The
myString
property is hoisted very close to the text field and the resulting two way data binding works very fast. Typing quickly on a keyboard shows the reflected input displayed on the screen with no hiccups. Example 2:
Copy code
val myString: String by myBusinessLogic.queryFlow.collectAsStateWithLifecycle(initial = "")
BasicTextField(
  value = myString,
  onValueChange = { 
    myBusinessLogic.persistMyString(it) // async call, this returns immediately.
  }
)
Here
myString
has been hoisted into some business logic component. Let’s imagine, for instance, that in this component we persist the
onValueChange
string in a SQLite DB and that we then query for such a string from the DB exposing it as a
Flow
which in the end updates the
value
string shown in the text field. This is where interactivity problems start: The round trip time of this two way data binding is of course greater because there’s a DB in between. Typing quickly on the keyboard or using keyboard auto repeat for long time starts showing some hiccups: sometimes you end up with some chars after where the cursor is. Intuitively I understand that I’m doing something “wrong” here, and that to keep the data on screen updating smoothly this 2 way data binding should happen “in memory” like in example 1. But how to do this and at the same time taking care of the write to the DB? Don’t we risk ending up duplicating state which is what the compose paradigm wants to avoid in the first place? Any suggestion is very appreciated.
a
I would say that storing on your bussiness logic must be a side effect; and not the main way to store. So I will go with first example and add a
Copy code
LaunchEffect(myString) { store(myString) }
After
myString = it
j
Thanks, but ain’t that technically “duplicated state”? We’d end up with that state (the string) both in the DB and in memory.
a
Yes, but in terms of composing it's more efficient this way. You don't really need to store each character, don't you? So is better to save it only when stops typing. You can do that with a coroutine job and delayed execution, while user is typing cancel old job every time, when stops typing last job executes and save. Setting a delay of ~300 ms should be enough
j
I remember I once got stuck in a very similar case: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1612543067398200 In that case @Zach Klippenstein (he/him) [MOD] was kind enough to help me get out of the mud.
c
I had a similar issue and I wrote a small todo app to come to a place where I could have only a single representation of my state