I have an issue with TextFields, namely that text ...
# ballast
s
I have an issue with TextFields, namely that text is being added in inconsistent places
I already tried setting dispatchers, which blocks the input entirely and I cannot edit the TextField at all,
Copy code
.dispatchers(
    inputsDispatcher = Dispatchers.Main.immediate,
    sideJobsDispatcher = Dispatchers.Default,
    interceptorDispatcher = Dispatchers.Default,
)
as well as using intermediary
mutableStateOf
, which also results in the above gif
Copy code
@Composable
fun CustomTextField(
    value: String,
    onValueChange: (String) -> Unit,
) {
    var text by remember { mutableStateOf(value) }

    LaunchedEffect(value) {
        text = value
    }

    OutlinedTextField(
        value = text,
        onValueChange = onValueChange,
    )
}
What works is updating the mutableState directly in the onValueChange lambda but I'm not sure if this will behave well when manipulating the input from within InputHandlers
Copy code
onValueChange = {
 text = it
 onValueChange(it)
}
What's the proposed way to handle TextField inputs?
c
This is a common problem generally with TextFields when the state is managed in a StateFlow instead of a
remember { mutableStateOf() }
block, and why the Compose team is working on a new implementation of TextFields to help mitigate the issues. This article is a good intro to the new TextField APIs, though do note that it’s still a WIP and not fully integrated into the Material libraries yet. Also, I haven’t actually tried out the new TextField to know exactly how well it works with the MVI model. The solution I typically use in the current TextField is to essentially just keep a copy of the TextFieldState’s text in the VM state, rather than having the VM state directly control the TextField. Something like this should work:
Copy code
var textFieldState by remember { mutableStateOf(TextFieldValue()) }
LaunchedEffect(uiState.text) {
    // after a very short delay, update the textFieldState with the text in the VM state.
    // this allows the VM to directly set the TextField's text, but avoid issues with UI inconsistency.
    // Ideally, this would only really apply if the VM manually changed the text (loaded it from DB, for example), 
    // and not as a result of normal user-entered input
    delay(25.milliseconds)
    if (uiState.text != textFieldState.text) {
        textFieldState = textFieldState.copy(text = uiState.text)
    }
}

TextField(
    value = textFieldState,
    onValueChange = {
        // set and display the text in the composition to maintain consistency
        textFieldState = it

        // send a copy of the text to the VM for validation, etc.
        postInput(ExampleContract.Inputs.TextChanged(it.text))
    },
)
s
I understand. I was a bit worried about inconsistencies, I suppose BasicTextField2 is good news however, wasn't aware of that at all ty