Jetpack Compose: Not able to show text in TextField

Viewed 1872

Recently I'm playing with Jetpack Compose and I noticed that the text may not show up in TextField.

So I have a ViewModel with Flow of ViewState.

In my Compose file, I have something similar to this:

@Composable
internal fun TestScreen() {
    val state by viewModel.state.collectAsState()
    TestScreen {
        viewState = state,
        actioner = { ... }
    }
}

@Composable
private fun TestScreen(viewState: ViewState, actioner: () -> Unit) {
    var name by remember {
        mutableStateOf(
            TextFieldValue(viewState.name)
        )
    }
    Surface {
        ....
        Column {
            ....

            OutlinedTextField(
                ...
                value = name,
                onValueChange = { textFieldValue -> 
                    name = textFieldValue
                    actioner(...)
                }
            )
        }
    }
}

the OutlineTextField will never show what's already inside viewState.name

However, if I change this:

    var name by remember {
        mutableStateOf(
            TextFieldValue(viewState.name)
        )
    }

To this:

    var name = TextFieldValue(viewState.name)

Obviously it could show the value in viewState.name.

According to the Documentation (https://developer.android.com/jetpack/compose/state#state-in-composables) in which it recommends using remember & mutableStateOf to handle the changes.

I'll be very grateful if someone could help me to explain why the code with remember doesn't work but the directly assigned value worked?

EDIT

viewState.name is a String

and I "partially solved" this issue by doing the following:

    var name by remember {
        mutableStateOf(
            TextFieldValue("")
        )
    }
    
    name = TextFieldValue(viewState.name)

then the name can be shown. But it doesn't look quite right?

1 Answers

remember is used just to ensure that upon recomposition, the value of the mutableStateOf object does not get re-initialised to the initial value.

For example,

@Composable
fun Test1(){
 var text by mutableStateOf ("Prev Text")
 Text(text)
  Button(onClick = { text = "Updated Text" }){
      Text("Update The Text")
  }
}

would not update the text on button click. This is because button click will change the mutableStateOf text, which will trigger a recomposition. However, when the control reaches the first line of the Composable, it will re-initialise the variable text to "Prev Text".

This is where remember comes in.

If you change the initialisation above to

var text by remember { mutableStateOf ("Prev Text") },

It wil tell compose to track this variable, and "remember" its value, and use it again on recomposition, when the control reaches the initialisation logic again. Hence, remember over there acts as a "guard" that does not let the control reach into the initialisation logic, and returns that latest remembered value of the variable it currently has in store.

Related