Understanding Stateful & Stateless in Jetpack Compose

My Jasmine Flower

Today I will briefly explain what Stateful & Stateless is in Jetpack Compose through code snippets based on my personal understanding when reading State and Jetpack Compose.

Based on Stateful versus stateless explanation. Stateful is when Composable create, holds and modifies its own State. Consider the following code:

@Composable
fun Greeting() {
val context = LocalContext.current

var isExpanded by remember { mutableStateOf(false) }
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
modifier = Modifier.weight(1f),
text = context.getString(R.string.lorem),
maxLines = if (!isExpanded) 4 else Int.MAX_VALUE
)
IconButton(
modifier = Modifier.align(Alignment.CenterVertically),
onClick = { isExpanded = !isExpanded }) {
Image(
imageVector = if (isExpanded) Icons.Filled.KeyboardArrowDown else Icons.Filled.KeyboardArrowUp,
contentDescription = ""
)
}
}
}

Greeting is a Stateful because it create, holds and modifies its own State and in this example isExpanded is the State

Stateful is useful when we don’t need to control the State of a Composable and we can use it without having to manage the state themselves.

However, according to the Stateful versus stateless explanation, the weakness of Stateful is that it tends to be less reusable and difficult to test.

Based on Stateful vs stateless explanation. Stateless is when Composable does not create, holds and modify its own State. Consider the following code:

@Composable
fun HelloScreen() {
var name by rememberSaveable { mutableStateOf("") }

HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Hello, $name",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
OutlinedTextField(
value = name,
onValueChange = onNameChange,
label = { Text("Name") }
)
}
}

HelloContent is an example of Stateless because it does not create, holds and modify its own State. Rather it only receive & hoist the State and this pattern is called State hoisting.

As you develop reusable Composables, you often want to expose both a Stateful and a Stateless version of the same composable. The Stateful version is convenient for callers that don’t care about the state, and the Stateless version is necessary for callers that need to control or hoist the State.

Always curious and always want to continue learning in many ways