I’m confuse the use of `SideEffect`. I cannot crea...
# compose
e
I’m confuse the use of
SideEffect
. I cannot create a case of to differentiate it’s use and without it’s use as per https://stackoverflow.com/questions/70720751/whats-the-different-using-sideeffect-and-not-using-it-in-jetpackcompose. Can someone enlighten? Thank you 🙏
b
Are you familiar with react hooks?
e
Sorry, I’m not familiar with react.
From what I read if the composition is successful, then the SideEffect will be triggered. I wonder how can I create a case to have a fail composition? I just want to experiment in such that the Composable code get called, yet the SideEffect is not triggered.
f
Side Effect is triggered every time your mutableStateOf that's wrapped in a remember gets updated
Also whenever your screen gets recomposed (config change etc..)
b
Not entirely true. SideEffect gets executed each time its dependencies change. If it has no dependencies, then it gets executed only when a composable first enters the composition
f
Side effect runs every time your compose tree is shaken, meaning that if you need to update non compose state that's where you'd do it
☝️ 1
a
You can throw an exception to experiment that.
@Big Chungus you are probably talking about
LaunchedEffect
and
DisposableEffect
. They are also side effects but the op is asking about
SideEffect
function here.
👍 1
💯 1
a
there aren't many easily reproducible cases of composition failure that you can create today without leaving the composition in a permanently corrupt and unusable state. Those are coming.
SideEffect {}
schedules the block of code you give it to run when the composition changes are applied. It's an output of the composition process but not directly to the composition's tree.
💯 1
This scheduling is unconditional. There is no snapshot observation happening inside the block you give to SideEffect, so if something inside there changes, it won't run again without some other reason for the composable function containing the
SideEffect
to recompose.
e
Thanks @Adam Powell. Thanks for more insight. I can understand this
Copy code
It's an output of the composition process but not directly to the composition's tree.
Can you provide an example of how to make this happen?
Copy code
if something inside there changes
I’m just trying to explore some tangible visible different between the two (With and Without SideEffect Block). I think if I can find how to trigger that
something
to
change
, I can see the different. The question is, what is that
something
, and how to make it
change
.
Identify how I can differentiate them now….
Copy code
@Composable
fun TrySideEffect() {
    var timer by remember { mutableStateOf(0) }
    Box(contentAlignment = Alignment.Center) {
        Text("Time $timer")
    }

    Thread.sleep(1000)
    timer++
}
and
Copy code
@Composable
fun TrySideEffect() {
    var timer by remember { mutableStateOf(0) }
    Box(contentAlignment = Alignment.Center) {
        Text("Time $timer")
    }

    SideEffect {
        Thread.sleep(1000)
        timer++
    }
}
Both will behave differently. Don’t think it’s the best way to explain
SideEffect
, but at least that’s one way to differentiate with without
SideEffect
. Also share my inputs in https://stackoverflow.com/a/70727052/3286489
a
Thread.sleep
in composition or in a
SideEffect
is always wrong
Both examples of updating a timer here are also wrong for reasons of data flow since they cause composition loops. Additionally, the first example of changing timer in composition is an example of an out of range write: it's invalidating state used by composition after it has already been used.
e
Agree the first example changing the timer is invalid. It is just to demonstrate the use of
SideEffect
. The
Thread.sleep
is just used to represent busy logic. So if one has a busy logic, it should never be placed in the composition function at all. At most, it can be placed in
SideEffect
. The above example is not the best way to explain the use of
SideEffect
, but it’s the simplest way I can think of to differentiate them without adding too many other things that makes understanding it complicated. Sorry, my brain is limited in digesting concept, making the simplest thing possible to help make sense out of things.
a
Thread-blocking logic shouldn't be placed in a
SideEffect
either. It will block the main thread before layout and drawing are permitted to proceed for the current frame.
e
Good point. Hard to think of a simple case that is still clear for the use of SideEffect. Any recommendation? If we want a simple loop timer, would you recommend using
LaunchEffect
or
SideEffect
or some other approach?
a
probably a
LaunchedEffect
. It's something that happens over time, which implies
suspend
, and you're describing it as a noun - "a [...] timer" - which implies that it has presence in the composition, it's not just a change that you apply to some other object.
👍 1
🙏 1
The use cases for
SideEffect
are pretty narrow. If you're trying to use composition to update some other object that isn't otherwise related to compose in any way, but creating a subcomposition with a custom applier would be overkill, it comes in handy.
🙏 1
👍 1