Thread
#compose-web
    Arjan van Wieringen

    Arjan van Wieringen

    2 months ago
    I have the issue that I have an
    Input
    which on recomposition doesn't update the UI with the latest value, but it is visible in the DOM tree. The code is a bit like this
    @Composable fun EditableTitle(value: String, onInputChange: (String) -> Unit = {}) {
        var editMode by remember { mutableStateOf(false) }
        val nativeElement = remember { mutableStateOf<HTMLInputElement?>(null) }
    
        // I need to use this as a hack to overwrite the value so that it works
        LaunchedEffect(value) {
            nativeElement.value?.value = value
        }
    
        LaunchedEffect(editMode, nativeElement.value) {
            when {
                editMode -> nativeElement.value?.select()
                !editMode && nativeElement.value != null -> {
                    nativeElement.value?.value?.also(onInputChange)
                    nativeElement.value?.blur()
                }
            }
        }
    
        Input(InputType.Text) {
            placeholder("Enter list name...")
            defaultValue(value) // when I use value(value) it blocks my UI
            refState(nativeElement) // this one uses DisposableEffect to fetch the nativeElement
    
            if (editMode && evt.key == "Enter") {
                editMode = false
            }
        }
    }
    I do some stuff with some other state variables to make it more UI friendly. The
    value
    parameter can be updated externally as well and when it has been modified at least once in the above Composable, the UI doesn't update if the input value into the composable is changed. When I use the
    LaunchedEffect(value)
    it works. Is this logical?
    o

    Oleksandr Karpovich [JB]

    2 months ago
    defaultValue
    sets only the initial value of the input. Subsequent changes of
    defaultValue
    won't do anything. Ideally, no LaunchedEffect(value) should be needed and using
    value
    should not block the UI. Do you have a minimal reproducer when
    value(value)
    leads to UI freeze?
    Arjan van Wieringen

    Arjan van Wieringen

    2 months ago
    Since it is a very basic use case the most obvious thing will be that I am being dumb. So I will create a minimal example and hopefully prove otherwise
    Okay, so I've reduced to this:
    fun main() {
        renderComposable("root") {
            MySimpleInput("Foo")
        }
    }
    
    @Composable fun MySimpleInput(
        value: String,
    ) {
        Input(InputType.Text) {
            value(value)
        }
    }
    I can't type anything in the input.
    When I remove
    value(value)
    I can type.
    And this works:
    attr("value", value)
    Looking in the source:
    fun defaultValue(value: Number): InputAttrsScope<ValueType> {
            attr("value", value.toString())
            return this
        }
    I don't know what to say.....
    hfhbd

    hfhbd

    2 months ago
    Do you want to update the value? Then you need a mutableState
    Arjan van Wieringen

    Arjan van Wieringen

    2 months ago
    Yes of course I want that, but I still would need to use
    value
    somehow right? So how would I do that then? Because even a minimal example freezes my input element.
    prop({ el: HTMLInputElement, v: String -> el.value = v}, value)
    This also works
    hfhbd

    hfhbd

    2 months ago
    This should work:
    fun main() {
        renderComposable("root") {
            var input by remember { mutableStateOf("Foo") }
            MySimpleInput(input) { input = it }
        }
    }
    
    @Composable fun MySimpleInput(
        value: String,
        onInput: (String) -> Unit
    ) {
        Input(InputType.Text) {
            value(value)
            onInput { onInput(it.value) }
        }
    }
    Arjan van Wieringen

    Arjan van Wieringen

    2 months ago
    You're right. But it got me totally confused, because it is subtlety different than Angular / React. For me it doesn't make sense that input-changes are not even registered when I don't update the mutableInput again. You know what I mean?
    hfhbd

    hfhbd

    2 months ago
    Yeah, you need to update the state manually. You could use the inputs uncontrolled, but this is not the (preferred) way. The android docs cover this topics deeply: https://developer.android.com/jetpack/compose/mental-model
    Arjan van Wieringen

    Arjan van Wieringen

    2 months ago
    Thanks a lot for helping again 🙂