hfhbd
01/30/2022, 4:12 PMrouting-compose:0.1.7 is out, with support for redirection if the routing tree changed. Simple use case: You got a link which requires a login first.
https://github.com/hfhbd/routing-composehfhbd
01/30/2022, 4:13 PMval isLoggedIn by remember { mutableStateOf(false) }
if (isLoggedIn) {
route("/foo") {
Text("Foo")
}
} else {
noMatch {
Button(onClick = { isLoggedIn = true }) { Text("Login")) }
}
}
Trying to access /foo without login results into showing the Login button, because route("/foo") is not available. After toggling isLoggedIn = true, this route is available, and visible.rocketraman
02/07/2022, 9:19 PMRouter.current in the sub-tree? Is this supposed to be supported?hfhbd
02/07/2022, 9:50 PMrocketraman
02/07/2022, 9:50 PM@Composable Top() {
BrowserRouter(initRoute = "/") {
route("/") {
Child()
}
}
}
@Composable Child() {
Router.current("/foo") {
route("/foo") {
...
}
route("/bar") {
...
}
}
}rocketraman
02/07/2022, 9:51 PMhfhbd
02/07/2022, 9:53 PMcurrent.invoke() and use only one router. What do you expect using different routers? What should happen, if calling navigate(to)?rocketraman
02/07/2022, 10:11 PMcurrent { ... } i.e. get a NavBuilder on the current router? The initRoute parameter is not optional.hfhbd
02/07/2022, 10:23 PMNavBuilder.current is currently not supported, and I don't think it will be in the future, because this class creates the route. CompositionLocalProvider is a tree based dependency injection, so although it is technically possible to update the CompositionLocalProvider in each call of route/int etc., I dont think this is a good idea. In generally, you should avoid using CompositionLocalProvider.current.
Instead just use @Composable NavBuilder.Child() { } or use @Composable Child(navBuilder: NavBuilder) { }hfhbd
02/07/2022, 10:27 PMrocketraman
02/07/2022, 10:30 PMrocketraman
02/07/2022, 10:33 PMRouter.current.navigate I guess must be aware of the entire hierarchy right? i.e. the Child must know about the paths of the parent elements to call navigate on one of its own routes?rocketraman
02/07/2022, 11:01 PMnoMatch if I actually want to display content, but what if I want to just navigate away immediately? I was thinking about some kind of onNoMatch callback where I can trigger a state change that would trigger the navigateTo, but maybe I'm approaching this the wrong way?rocketraman
02/07/2022, 11:28 PM/top have the router automatically forward me to /top/a. I can do that now by checking window.location but doesn't seem like it should be necessary.hfhbd
02/08/2022, 9:58 AM/a and /top and /top/a as possible routes. You are at /top. when you call navigate(to="/a"), you must distinguish to go to different routes, either via a second parameter or via Router.current and Router.root 🤔hfhbd
02/08/2022, 9:59 AMnoMatch { LaunchedEffect(Unit) { Router.current.navigate(to="/top/a") } }rocketraman
02/08/2022, 1:47 PMnavigateTo(to="foo") for a route at the same "level" as a current one, or navigateTo(to="../foo/bar") for a child of a parent route.rocketraman
02/08/2022, 1:49 PMnoMatch { LaunchedEffect(Unit) { Router.current.navigate(to="/top/a") } } doesn't work as-is because navigateTo is an @Composable invocation. This pattern seems to work, but looks very boiler-platey:
val (navigateTo, setNavigateTo) = remember { mutableStateOf<String?>(null) }
if (navigateTo != null) {
setNavigateTo(null)
Router.current.navigate(to = navigateTo)
}
...
noMatch {
LaunchedEffect(Unit) { setNavigateTo("/whatever") }
}hfhbd
02/08/2022, 2:23 PMRouter.current is @Composable, navigateTo isn't
val router = Router.current
LaunchedEffect(Unit) {
router.navigate(to = "a")
}hfhbd
02/08/2022, 2:24 PMnavigate, eg: navigate(to="a", relative = true)rocketraman
02/08/2022, 2:26 PMRouter.current is @Composable, navigateTo isn'tAh, ok. Still a bit messy to have to use that saved router reference, but better for sure.
rocketraman
02/08/2022, 2:28 PMBut relative paths also requires knowing the full hierarchy.Why do you say that?
I dont like parsing relative paths 😄 So one option would be using another parameter in navigate, eg: navigate(to="a", relative = true)That would work.
hfhbd
02/08/2022, 2:56 PMroute("/foo") {
Text("Foo")
route("/a) {
Text("A")
}
noMatch {
Text("Else")
}
}
Well, the current design of routing-compose is in fact a (recursive) functional `when`:
val currentPath = currentURL.currentPath
when(currentPath) {
is "foo" -> {
Text("Foo")
val currentPath = currentPath.currentPath
when(currentPath) {
is "/a" -> {
Text("A")
}
else (noMatch) -> {
Text("Else")
}
}
}
is Int ->...
}
So to support navigate(to = "a", relative = true), you need an instance of NavBuilder in the correct sub tree, otherwise it is impossible to resolve the relative path!
Actual, the Router does not know the current state (subtree) of NavBuilder, but this must be implemented in an update.
So in each subtree, it is necessary to update NavBuilder.current (does not exists yet) and map it to Router.current... This requires a lot using CompositionLocal (which requires current @Composable getter by design).
You should only use Router.current to get a reference deep in your UI, and this value is only set once at the start of your application. NavBuilder.current needs to be updated every recomposition, in every child Composable, only to "save" a parameter.
Workaround: Use a reference: Receiver @Composable fun NavBuilder.A() or parameter @Composable fun A(navBuilder: NavBuilder) and full paths.rocketraman
02/08/2022, 3:08 PMYou should only use Router.current to get a reference deep in your UI, and this value is only set once at the start of your application.But
NavBuilder has no reference to Router. It can define routes, but AFAICT I still need to do Router.current to use navigate.hfhbd
02/08/2022, 3:09 PMrelative support yet 😄rocketraman
02/08/2022, 3:10 PMhfhbd
02/08/2022, 3:11 PMinline val NavBuilder.router @Composable get() = Router.currenthfhbd
02/08/2022, 3:11 PMNavBuilder.router insteadrocketraman
02/08/2022, 3:12 PMrocketraman
02/08/2022, 3:14 PMrocketraman
02/08/2022, 3:22 PMgetPath but unsure of why that takes an initPathhfhbd
02/08/2022, 3:32 PMLaunchedEffect.
See https://github.com/hfhbd/ComposeTodo/pull/464/files for a samplerocketraman
02/08/2022, 3:44 PMrocketraman
02/08/2022, 3:57 PMhfhbd
02/08/2022, 4:04 PMNavBuilder in each route...hfhbd
02/08/2022, 4:04 PMrocketraman
02/08/2022, 4:19 PMTo update your navigation bar, you need to pass your current active route to the navbar by using LaunchedEffect.This doesn't work consistently.
LaunchedEffect is not always triggered.rocketraman
02/08/2022, 4:20 PMrocketraman
02/08/2022, 4:26 PMLaunchedEffect seems to work:
string { urlSegment ->
LaunchedEffect(urlSegment) {
setCurrentTab(tabs.singleOrNull { it.urlSegment == urlSegment })
}
...
}rocketraman
02/08/2022, 5:14 PMnavigate to not push the navigation onto the back stack.rocketraman
02/08/2022, 5:15 PMrocketraman
02/09/2022, 2:27 PM@Routing annotation do anything?hfhbd
02/09/2022, 2:59 PM