lesincs
07/28/2021, 1:28 PMstate
and call the `ViewModel`’s function directly.
For example,if we have a login screen。Our ViewModel
may look like this:
class LoginViewModel : ViewModel() {
private val _state = MutableStateFlow(LoginScreenState())
val state: StateFlow<LoginScreenState>
get() = _state.asStateFlow()
'' fun onUserNameChange(userName: String) {
_state.value = state.value.copy(userName = userName)
}
// ......... ignore other function ..........
'}
'data class LoginScreenState(
val isLogin: Boolean = false,
val userName: String = "",
val password: String = ""
)
The screen is like this:
@Composable
fun LoginScreen() {
//...
UserName()
PassWord()
//......
}
@Composable
fun UserName(){
val viewModel = viewModel<LoginViewModel>()
val state by viewModel.state.collectAsState()
TextField(value = state.userName,onValueChange = {
viewModel.onUserNameChange(it)
})
}
Some one may wonder why we don’t do state hoisting
, because in the official pathway, they do state hoisting
, and in some official demos, they do state hoisting
as well.
But we use compose
in a commercial project instead of a demo, so in our project, our compose
hierarchy is much deeper than the demo. So there may be so many properties or action we need to state hoisting
, it’s a pretty painful process. So we just write code in below way, the benefit is we can get the sate of the screen easily, and we can just call the function of ViewModel
directly.
But there is a concern in my mind that is even only the password’s state change will toggle the UserName
composable recomposition, so I’m not sure if there is a performance problem in our way.
Also I think in our way updating a state is painful process as well. We need to write this boilerplate everywhere。
_state.value = state.value.copy(userName = userName)
So I want to ask for if there are some good way to manage state?Zach Klippenstein (he/him) [MOD]
07/28/2021, 3:54 PMlesincs
07/29/2021, 12:41 AMstate hoisting
, so my question is do I need to make any none-top Composable
stateless?
2. Secondary, you said “Changing the password state shouldn’t trigger a recomposition of the username ..“, but both of them observes just one same state, right? Is there some optimization Compose
did under the hood?
3. For the reducer libraries, I will take a look at them, thanks.Zach Klippenstein (he/him) [MOD]
07/29/2021, 3:39 PMval userName = state.map { it.userName }
Note that this is an assignment, not a get()
override – that’s important because the assignment creates a single new Flow which will be used by every recomposition, whereas doing the map in a get()
would create a new flow every call, which would technically work in this case but would be wasteful and could cause issues in the future.If that’s isI’m not sure why you’re asking. State hoisting is just the name for a pattern that comes up a lot with declarative frameworks. There are different ways to hoist state. Whether your composables should be stateless or not depends on what kind of API it makes sense for them to provide. If you want them to be stateless, you might find state hoisting a useful tool., so my question is do I need to make any none-topstate hoisting
stateless?Composable