Skip to content
dimsuz edited this page May 19, 2022 · 6 revisions

Rule ReusedModifierInstance

Finds usages of the modifier parameter on non-top-level children of a composable function. This tends to happen during refactorings and often leads to incorrect rendering of a composable.

For example, imagine that Column here used to be a top composable, but then it got wrapped by the Row. But the modifier parameter was moved along with it and is now applied to the wrong composable:

@Composable
fun MyComposable(modifier: Modifier) {
  Row(modifier = Modifier.padding(30.dp)) {
    Column(modifier = modifier.padding(20.dp)) {
    }
  }
}

@Composable
fun Content() {
  MyComposable(modifier = Modifier.background(color = Color.Green))
}

This should be fixed by using modifier parameter on the Row instead:

@Composable
fun MyComposable(modifier: Modifier) {
  Row(modifier = modifier.height(30.dp)) {
    Column(modifier = Modifier.padding(20.dp)) {
    }
  }
}

Rule UnnecessaryEventHandlerParameter

Suggests hoisting event argument passing to the upper level which often simplifies individual composable components. This makes individual components less coupled to the structure of their parameters and leaves that to the parent, which in turn often leads to simplification of a composable.

For example here the PrettyButton is unnecessary coupled to the structure of Data — it extracts id field inside the onClick:

data class Data(id: Int, title: String)

fun PrettyButton(data: Data, onAction: (Int) -> Unit) {
  Button(onClick = { onAction(data.id) })
}

fun Parent() {
  val data = Data(id = 3, title = "foo")
  PrettyButton(data = data, onAction = { id -> process(id) })
}

This "knowledge" of id can be moved to the parent which would not only simplify the PrettyButton by removing unnecessary lambda wrapper around onAction call, but this also makes it easier to work with PrettyButton later, during refactorings. Here the data.id is hoisted into the parent:

fun PrettyButton(data: Data, onAction: () -> Unit) {
  Button(onClick = onAction)
}

fun Parent() {
  val data = Data(id = 3, title = "foo")
  PrettyButton(data = data, onAction = { process(data.id) })
}

Rule ComposableEventParameterNaming

Ensures that all event handler parameters of composable functions are named in the same Compose-like style, i.e. they have on prefix and do not use past tense.

This rule suggests naming improvements

fun Button(click: () -> Unit) // ❌ wrong: missing "on"
fun Button(onClick: () -> Unit) // ✅ correct

fun Box(scroll: () -> Unit) // ❌ wrong: missing "on"
fun Box(onScroll: () -> Unit) // ✅ correct

fun Box(onScrolled: () -> Unit) // ❌ wrong: using past tense
fun Box(onScroll: () -> Unit) // ✅ correct

Rule ModifierHeightWithText

Suggests using Modifier.heightIn() instead of Modifier.height() on a layouts which have Text children, so that if the text turns out to be long and would overflow and wrap, layout will not cut it off

Row(modifier = Modifier.height(24.dp)) {
  Text("hello")
}

with

Row(modifier = Modifier.heightIn(min = 24.dp)) {
  Text("hello")
}

Rules ModifierArgumentPosition and ModifierParameterPosition

Ensure that modifier is declared and passed as a first parameter/argument:

Button(
  arrangement = Vertical,
  modifier = Modifier,
)

Button(arrangement = Vertical, modifier = Modifier.padding(24.dp))

Should be replaced with:

Button(
  modifier = Modifier,
  arrangement = Vertical,
)

Button(modifier = Modifier.padding(24.dp), arrangement = Vertical)

Rule PublicComposablePreview

Finds and reports composable previews which are not marked as private

Clone this wiki locally