https://kotlinlang.org logo
Title
v

vide

06/30/2022, 11:43 AM
Is it better to store individual class properties as MutableState or the whole class? (Example of what I mean in 🧵)
/* Screen 1 */
data class ScreenState(
    val firstName: String,
    val lastName: String,
)

@Composable fun Screen() {
    val screenState = remember { mutableStateOf(ScreenState("Hello", "World")) }
    SomeComponent(
        firstName = screenState.value.firstName,
        lastName = screenState.value.lastName,
        setFirstName = { screenState.value = screenState.value.copy(firstName = it) }
    )
}

/* Screen 2 */
class ScreenState2() {
    private val _firstName = mutableStateOf("Hello")
    val firstName: State<String> get() = _firstName
    fun setFirstName(name: String) { _firstName.value = name }
    
    private val _lastName = mutableStateOf("World")
    val lastName: State<String> get() = _lastName
}

@Composable fun Screen2(screenState: ScreenState2) {
    SomeComponent(
        firstName = screenState.firstName.value,
        lastName = screenState.lastName.value,
        setFirstName = screenState::setFirstName,
    )
}

@Composable fun SomeComponent(firstName: String, lastName: String, setFirstName: (String) -> Unit) {
    TODO()
}
What is the practical difference here? Any performance benefits?
I'd prefer the second approach since especially with complex state I'd imagine updating some deeply nested state would become quite troublesome with the first approach, but is my intuition wrong here?
👀 1
s

ste

06/30/2022, 11:47 AM
You could also do:
class ScreenState(
    firstNameState: MutableState<String>,
    lastNameState: MutableState<String>,
) {
    var firstName by firstNameState
    var lastName by lastNameState
}

@Composable
fun rememberScreenState() {
    val firstNameState = rememeber { mutableStateOf("") }
    val lastNameState = rememeber { mutableStateOf("") }

    return remember {
        ScreenState(firstNameState, lastNameState)
    }
}
z

Zoltan Demant

06/30/2022, 12:49 PM
I think the latter approach is slightly better, at least it should result in fewer recompositions if only one of the fields change
m

myanmarking

06/30/2022, 1:20 PM
No, i don’t think that is true
2
c

Casey Brooks

06/30/2022, 1:26 PM
I’m strongly of the opinion that using a data class is much better than individual
States
for each property. The high-level reasoning is that it is difficult to combine those individual properties if you need to use both values at once, but combining properties is trivial when the state is just an immutable data class. I’ve got a much more in-depth discussion on how to model state in the documentation for my MVI library, ballast
👍 2
👍🏽 1
m

myanmarking

06/30/2022, 1:50 PM
exactly
a

agrosner

06/30/2022, 2:29 PM
Much easier to reason about changes with a single data class for state
Otherwise you can end up with many individual fields to manage
👆 1
c

Colton Idle

06/30/2022, 2:50 PM
For me, I typically just have each screen state with a bunch of mutableStateOf. Seems to work fine /shruggie
a

agrosner

06/30/2022, 2:53 PM
Idk if I recommend that either. Why need that when compose does smart diffing anyways?
m

myanmarking

06/30/2022, 2:54 PM
for me, one screen one data class
c

Colton Idle

06/30/2022, 2:55 PM
Def seems to be stylistic differences, but curious what the compose team says here. I am but a simple noob at this stuff.
❤️ 1
a

Albert Chang

06/30/2022, 3:52 PM
I think there are already many discussions on this. For example this thread.
❤️ 1
a

agrosner

06/30/2022, 4:26 PM
Also the memory overhead of state for each smal string or variable. And initialization overhead of registering each one. Keep state small in places it's used and break the data class into smaller reusable pieces
v

vide

06/30/2022, 7:43 PM
Thanks everyone for the answers 😄