David Herman
08/21/2024, 12:44 AMDavid Herman
08/21/2024, 12:45 AM@Composable
fun Common(content: @Composable () -> Unit) {
val someValue = remember { … }
…
}
@Composable
fun First() {
Common {
…
}
}
@Composable
fun Second() {
Common {
…
}
}
I would love to tell compose that no matter how I enter Common
, I want the remembered state (i.e. someValue
) not to be reset.David Herman
08/21/2024, 12:46 AM@Composable
fun SomePage() {
SidebarLayout { ... }
}
@Composable
fun AnotherPage() {
SidebarLayout { ... }
}
And then later registered:
router.register("/some-page") {
SomePage()
}
router.register("/another-page") {
AnotherPage()
}
Of course, every time a page is visited, the layout composable, since it is a child of the page, is recomposed, and any state within it (such as which sidebar elements are expanded / collapsed) is reset.Ian Lake
08/21/2024, 1:12 AMDavid Herman
08/21/2024, 1:12 AMDavid Herman
08/21/2024, 1:13 AMDavid Herman
08/21/2024, 1:14 AMDavid Herman
08/21/2024, 1:15 AMCommon {
when (page) {
"some-page" -> SomePage()
"another-page" -> AnotherPage()
}
}
but I'm unfortunately inverting this relationshipIan Lake
08/21/2024, 1:15 AMDavid Herman
08/21/2024, 1:16 AMmovableContentOf
but for parent containersDavid Herman
08/21/2024, 1:16 AMIan Lake
08/21/2024, 1:18 AMDavid Herman
08/21/2024, 1:18 AMregister
example above, if I extract layouts:
router.register(
"/some-page",
layout = { CommonLayout() }
) {
SomePage()
}
router.register(
"/another-page",
layout = { CommonLayout() }
) {
AnotherPage()
}
but because of the wrapping lambda, Compose still recomposes the layoutDavid Herman
08/21/2024, 1:19 AMIan Lake
08/21/2024, 1:21 AMlayout = { sharedContent ->
sharedContent()
// Other content
}
David Herman
08/21/2024, 1:24 AMDavid Herman
08/21/2024, 1:25 AM@Composable
fun SomePage() {
SidebarLayout { ... }
}
@Composable
fun AnotherPage() {
SidebarLayout { ... }
}
@Composable
fun TutorialPage() {
DocsLayout { ... }
}
Ian Lake
08/21/2024, 1:26 AMDavid Herman
08/21/2024, 1:27 AMDavid Herman
08/21/2024, 1:28 AMval layoutA = movableContentOf(...)
val layoutB = ...
val layoutC = ...
when (page) {
0 -> layoutA { ... }
1 -> layoutA { ... }
2 -> layoutB { ... }
3 -> layoutB { ... }
4 -> layoutC { ... }
}
and that basically treated each branch as a new call and reset my stateDavid Herman
08/21/2024, 1:30 AMDavid Herman
08/21/2024, 1:32 AMApp -> SomePage -> CommonLayout
App -> AnotherPage -> CommonLayout // don't recompose
App -> TutorialPage -> DocsLayout // ok to recompose
I appreciate this may not be possible, or I might even be thinking about things wrong, but I thought I'd ask in case there was a tool in the compose toolkit I wasn't aware ofDavid Herman
08/21/2024, 1:32 AMmovableContentOf
would let me do it but I couldn't figure it out.David Herman
08/21/2024, 1:40 AM@Composable
fun Common(content: @Composable () -> Unit) {
val commonValue = remember { Random.nextInt() }
println("Common value is $commonValue")
content()
}
@Composable
fun SomePage() {
Common { println("Some page") }
}
@Composable
fun AnotherPage() {
Common { println("Another page") }
}
@Composable
fun PageSelector() {
var currentPage by remember { mutableStateOf(0) }
Button(onClick = { currentPage = (currentPage + 1) % 2 }) { Text("Change the current page") }
when (currentPage) {
0 -> SomePage()
1 -> AnotherPage()
}
}
David Herman
08/21/2024, 1:43 AMwhen
block is hand written, but in practice, the current page is being driven by the user typing a URL into the browser, which in turn updates the active page and re-renders it.
Still, the above case should help exemplify the problem I have. if you have the console open, you'll see that the int value is reset each time a new page is composed, whereas I want to figure out how to keep that int value in Common
the same across pages.David Herman
08/21/2024, 1:49 AMmovableContentOf
that doesn't work, potentially exposing a misunderstanding I have of the concept:
@Composable
fun Common(content: @Composable () -> Unit) {
val commonValue = remember { Random.nextInt() }
println("Common value is $commonValue")
content()
}
@Composable
fun SomePage(layout: @Composable (@Composable () -> Unit) -> Unit) {
layout { println("Some page") }
}
@Composable
fun AnotherPage(layout: @Composable (@Composable () -> Unit) -> Unit) {
layout { println("Another page") }
}
@Page
@Composable
fun HomePage() {
var currentPage by remember { mutableStateOf(0) }
Button(onClick = { currentPage = (currentPage + 1) % 2 }) { Text("Change the current page") }
val layout = movableContentOf<@Composable () -> Unit> { content -> Common(content) }
when (currentPage) {
0 -> SomePage(layout)
1 -> AnotherPage(layout)
}
}