Table of contents
Introduction
- Lately I have been trying to find ways to refactor my Jetpack compose functions and thankfully I stumbled across the Twitter Compose Ruleset, which can be found HERE.
- What the
Twitter Compose Ruleset
actually is, is a set of custom ktlint rules to ensure that your composables don't fall into common pitfalls, that might be easy to miss in code reviews. You can even find a tutorial on how to set it up with ktlin HERE. But for right now we are going to focus on hand refactoring some code from my latest app.
My latest app for cattle farmers in North America
The GitHub
The code we will be refactoring:
- The code below is the code we will be refactoring by applying the rules found HERE
@Composable
fun CalendarDock(viewModel: EditCalfViewModel){
val calfDate = viewModel.uiState.value.birthDate!!
val convertedDate = calfDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
val selectedDate = remember {
mutableStateOf<LocalDate?>(convertedDate)
}
val calendarState = rememberSheetState()
CalendarDialog(
state = calendarState,
config = CalendarConfig(
monthSelection = true,
yearSelection = true
),
selection = CalendarSelection.Date(selectedDate = selectedDate.value){ newDate ->
selectedDate.value = newDate
viewModel.updateDate(newDate)
}
)
Row(
horizontalArrangement = Arrangement.SpaceBetween) {
OutlinedTextField(
//state
enabled = false,
value = "Date born: "+ selectedDate.value.toString(),
onValueChange = { },
//style
singleLine = true,
placeholder = {
Text(text = "Date", fontSize = 20.sp)
},
modifier = Modifier
.fillMaxWidth(),
textStyle = TextStyle(fontSize = 20.sp),
)
}
}
Mistake 1: Passing a ViewModel as parameter
- Notice in the signature of the compose function I am passing in a viewModel as a parameter:
fun CalendarDock(viewModel: EditCalfViewModel)
- As stated in the RULES, instead of passing a viewModel, we should pass in the relevant data or an optional lambda
Mistake 2: No modifier parameter
- Notice how this code above has no
modifier
parameter. This is a serious red flag when writing compose code. Every composable function (yes I do mean literally every compose function) should have a modifier parameter. The main reason for this is because it promotes flexibility and code reuse but if you want a deeper understanding I recommend you read the blog post HERE
Mistake 3: Position of the modifier parameter
- When adding the modifier parameter we should make sure to add it in the correct position. When adding parameters to compose functions, the mandatory parameters come first and then comes the modifier parameter. The modifier parameter should occupy the first optional parameter slot to set a consistent exception for other developers. This means as our project grows and we add more people to our team, they can expect a consistent programming experience.
Mistake 4: Modifiers should have default parameters
as the rules state:
Composables that accept a Modifier as a parameter to be applied to the whole component represented by the composable function should name the parameter modifier and assign the parameter a default value of Modifier
.Long story should if you have a modifier parameter you should give it a default value of Modifier
Refactored code:
- So with all these rules applied our refactored code now looks like this:
@Composable
fun CalendarDock2(dateBorn: Date,selectedAction:(LocalDate)->Unit,modifier: Modifier = Modifier){
val convertedDate = dateBorn.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
val selectedDate = remember { mutableStateOf<LocalDate?>(convertedDate) }
val calendarState = rememberSheetState()
CalendarDialog(
state = calendarState,
config = CalendarConfig(
monthSelection = true,
yearSelection = true
),
selection = CalendarSelection.Date(selectedDate = selectedDate.value){ newDate ->
selectedDate.value = newDate
selectedAction(newDate)
}
)
Row(
horizontalArrangement = Arrangement.SpaceBetween,
) {
OutlinedTextField(
//state
enabled = false,
value = "Date born: "+ selectedDate.value.toString(),
onValueChange = { },
//style
singleLine = true,
placeholder = {
Text(text = "Date", fontSize = 20.sp)
},
modifier = modifier,
textStyle = TextStyle(fontSize = 20.sp),
)
}
}
Conclusion
- Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.
Top comments (0)