You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently there is no (lint) warning when using derivedStateOf without accessing any State object in its calculation, which can lead to unexpected behaviour. Since no State object is read, the derived value will never update which however might not be obvious just by looking at the code.
Let's take the following Composable for example:
@Composable
funAmount(
amount:Int,
modifier:Modifier = Modifier,
) {
val isZeroAmount by remember { derivedStateOf { amount ==0 } }
Box(modifier = modifier) {
if (isZeroAmount) {
Text("Amount: Is zero")
} else {
Text("Amount: $amount")
}
}
}
If amount is 1 initially and becomes 0 on the next recomposition, the Composable will incorrectly display Amount: 0 instead of Amount: Is zero.
This might for instance happen when a State variable with by delegation is changed to a plain type.
The correct code for this case would be:
@Composable
funAmount(
amount:State<Int>,
modifier:Modifier = Modifier,
) {
val isZeroAmount by remember { derivedStateOf { amount.value ==0 } }
Box(modifier = modifier) {
if (isZeroAmount) {
Text("Amount: Is zero")
} else {
Text("Amount: ${amount.value}")
}
}
}
The text was updated successfully, but these errors were encountered:
I assumed that this will be a tricky one without type resolution in the context of the rule's code. Also just ensuring that any read inside the calculation must be done via state.value is not sufficient when by delegation is used.
I like it! It's going to be hard to determine whether something is backed by state though. There's the obvious case of having a State object in the same function, but the state could be anywhere in the call stack, and possible hidden through lambdas or other objects.
I think a better way is for derivedStateOf to throw an exception, when it detects that nothing state backed has been read.
I like the idea of derivedStateOf throwing an exception. It even becomes trickier when a State is read inside the calculation which however is not part of the resulting value. Then the derived state only updates when the unrelated state is updated, which might be even more confusing.
val isZeroAmount by remember {
derivedStateOf {
log("Product type is: ${productType.value}") // productType is State<String> for example
amount ==0
}
}
I think only the Compose compiler or runtime can detect those cases for certain.
Currently there is no (lint) warning when using
derivedStateOf
without accessing anyState
object in its calculation, which can lead to unexpected behaviour. Since noState
object is read, the derived value will never update which however might not be obvious just by looking at the code.Let's take the following Composable for example:
If
amount
is1
initially and becomes0
on the next recomposition, the Composable will incorrectly displayAmount: 0
instead ofAmount: Is zero
.This might for instance happen when a
State
variable withby
delegation is changed to a plain type.The correct code for this case would be:
The text was updated successfully, but these errors were encountered: