How anal is it to use state hoisting? My screen pa...
# compose
n
How anal is it to use state hoisting? My screen params are starting to build up a lot of `OnClick() -> Unit`’s . Is it preferred that I pass the viewmodel around at this point? I was trying to avoid that because then I can’t preview the screen at all.
2
t
Anal? 👀
🍑 6
s
On the preview, you are supposed to just pass something like
onClick = {}
and it will work just fine.
n
right, and I am. But now I have to pass that through all the different layers. Should I be using
CompositionLocal
for click events? Is that appropriate?
t
No not at all. I personally build the layout with hard coded data first and view them in the preview then add view model latter.
n
That’s what I was thinking too, but then the preview stops working because of the ViewModel
s
Just pass it thought all the different layers, is that too much? Maybe consider doing something like this:
Copy code
@Composable
fun MyScreen(stuff: Whatever, navigationActions: NavigationActions)

class NavigationActions(whatever: Any) {
    val doSomething: () -> Unit { // stuff }
    val doSomethingElse: () -> Unit {}
}
Where NavigationActions could be whatever fits your use case, usually those actions have some logical grouping that can fit them inside one/more class(es) And then on the composable that takes this actions class, call the leaf composable that will just take them individually something like
Copy code
@Composable
fun MyScreen(actions: NavigationActions) {
    val viewModel: MyViewModel = hiltViewModel()

    MyScreen(
        setThis = { clickedSomething ->
            viewModel.setSomething(clickedSomething)
        },
        goToDetailsScreen = { someId: Int ->
            actions.goToDetailsScreen(someId)
        },
        goBack = {
            actions.goBack()
        },
    )
}
Then you can pass your actions whatever they may be bundled inside one class and pass that down the hierarchy?
2
n
🎉 1
c
yep. state down events up keeps everything testable and reusable. seems right to me!
z
One other thing that might help (depending on your situation) is to take a more slot-based approach, where instead of passing down specific data and even handlers through multiple layers, the intermediate layers just take a composable function (i.e. a “slot”) and then you just pass the data and handler lambdas down by capturing them in a lambda at the top level. So instead of
Copy code
fun A() {
  B(a)
}
fun B(b) {
  C(b)
}
fun C(c) {
  D(c)
}
You would have
Copy code
fun A() {
  B {
    D(a)
  }
}
fun B(content: @Composable () -> Unit) {
  C(content)
}
fun C(content: @Composable () -> Unit) {
  content()
}
💯 1
👍 1
❤️ 1