Issue
I have a TextField
for a search query and a Button
that will execute the search and the results are shown in a column. Since the search takes a few seconds to run I want it to be executed on button press and not on text change.
Here is a simplified demonstration:
Column {
val list = remember { mutableStateListOf<String>() }
val textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
TextField(
value = textFieldValue.value,
onValueChange = { textFieldValue.value = it }
)
Button({
list.clear()
list.addAll(textFieldValue.value.text.split(""))
}) {
Text("Search")
}
list.forEach {
println("test")
Text(it)
}
}
After the first time that the button is pressed, the foreach loop will run on text change. Even clicking on the TextField
will rerun the loop. This doesn't run the search on text change, but re-renders the results and that causes glitches while typing in the text field.
How can this be prevented?
Solution
The above is true for Jetpack Compose. The author wanted to know about Compose Desktop, and it's not the same there yet, because it's in alpha and is not optimised that much yet.
Modifying a remember
value always leads to a recomposition of all views, which its read value.
Any changes to value will schedule recomposition of any composable functions that read value.
documentation
The way to stop it is moving out all views that reads remember
value into a separate view. It'll be recomposed for each remember
value change, but it won't will affect the container.
In your case it's pretty simple: just move TextField
and pass textFieldValue
into the new function. You can forward all params you need, like modifier
, textStyle
, etc.
@Composable
fun TestView(
) {
Column {
val textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
val list = remember { mutableStateListOf<String>("test") }
TextField(textFieldValue)
Button({
list.clear()
list.addAll(textFieldValue.value.text.split(""))
}) {
Text("Search")
}
list.forEach {
println("test $it")
Text(it)
}
}
}
@Composable
fun TextField(
textFieldValue: MutableState<TextFieldValue>,
) {
TextField(
value = textFieldValue.value,
onValueChange = { textFieldValue.value = it }
)
}
I'm not sure why there's no system function with this semantics, but in compose they prefer State hoisting pattern to match UDF.
Answered By - Philip Dukhov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.