Youssef Shoaib [MOD]
03/24/2024, 11:37 AMRaise
doesn't mesh nicely with it because Compose doesn't fully support exceptions. Anyone have some experience with this and knows if there's a way to improve the ergonomics of Compose + Raise?CLOVIS
03/24/2024, 11:59 AMRaise
in a @Composable
functions themselves.
However, that's different in event handlers, since those are allowed to have business logic, suspend, etc. What I do is create a simple function that introduces a Raise
scope and reports it to a MutableState
;
@Composable
fun SomeForm(…) {
var failure by remember { mutableStateOf<DomainFailure?>(null) }
…your form…
SubmitButton(
onClick = {
recover(
block = { …business logic… },
recover = { failure = it }
)
}
)
}
CLOVIS
03/24/2024, 12:03 PM@Composable
fun ShowUser(userId: String) {
val user by remember { userService.get(userId).collectAsState() }
user.onFailure {
Text("Could not get user")
}
user.onSuccess {
ShowUser(it)
}
user.onLoading {
LoadingSpinner()
}
}
Youssef Shoaib [MOD]
03/24/2024, 12:29 PM@Composable
fun Raise<UserError>.ShowUser(userId: String) {
val user by remember { userService.get(userId).collectAsState() }
if (user is Loading) LoadingSpinner() else ShowUser(user.bind())
}
(Can't seem to find an Outcome.bind()
from a quick skim thru Pedestal, but just imagine this is an Either
for the sake of the argument)
So that someone on the outside can provide the Text("Could not get user")
part. I'm guessing that likely isn't supportedCLOVIS
03/24/2024, 1:22 PMOutcome.bind()
is here, but yeah Outcome
is the same thing as Either
. It exists as a parallel to ProgressiveOutcome
, which adds the in-progress variants. When context receivers arrive, they will all finally be fully interchangeable through Raise
.
So that someone on the outside can provide theSorry, I don't understand this.part. I'm guessing that likely isn't supportedText("Could not get user")
Youssef Shoaib [MOD]
03/24/2024, 1:23 PMrecover({ ShowUser("foo") }) { Text("Could not get user") }
CLOVIS
03/24/2024, 1:25 PMrecover
is inline, right? So you can do that 🤔Youssef Shoaib [MOD]
03/24/2024, 1:26 PMCLOVIS
03/24/2024, 1:27 PMrecover({ ShowUser("foo") }…)
makes no sense: ShowUser
is a data→UI mapper, it shouldn't contain logic, so there is no legitimate case where it raises.
It's not just an ideological decision: composable functions recompose, so "calling a composable function" means something completely different than calling a regular function. Because of caching, it may not actually be called, or it may be called multiple times.Youssef Shoaib [MOD]
03/24/2024, 1:29 PMEither<Unit, UserError>
, then it'd work just fine.
Btw, for my use case, I'm using Compose to produce data, not UI. I'm trying to play around with Molecule to make List Comprehensions, and not being able to Raise
has made handling certain corner cases harder.CLOVIS
03/24/2024, 1:30 PMOne curious thing though is that you can do something similar with a return type. E.g. if we returned anYes, because it binds the return value to the parent composable, so if it changes the parent also recomposes., then it'd work just fine.Either<Unit, UserError>
Youssef Shoaib [MOD]
03/24/2024, 1:31 PMRaise
would work very well.CLOVIS
03/24/2024, 1:31 PMBtw, for my use case, I'm using Compose to produce data, not UI. I'm trying to play around with Molecule to make List Comprehensions, and not being able toYeah, in that case I think you're stuck with returninghas made handling certain corner cases harder.Raise
Either
.
Compose really is made to produce a tree, not returning data directly…CLOVIS
03/24/2024, 1:32 PMRaise
-ble function, and then folding the tree latersimon.vergauwen
03/25/2024, 8:24 AMtry/catch
outside of @Composable
but only in a single node of the tree?CLOVIS
03/25/2024, 8:32 AM@Composable
functions are often called by the runtime itself rather than by their parent, so thrown exceptions are in the runtime's stack and you can never catch them.
https://www.reddit.com/r/androiddev/comments/19evp8n/how_do_you_handle_uncaught_exceptions_in_compose/simon.vergauwen
03/25/2024, 9:47 AMCompose
is truly a sublanguage, it's not just Kotlin.CLOVIS
03/25/2024, 9:48 AMCLOVIS
03/25/2024, 9:48 AMCLOVIS
03/25/2024, 9:51 AM