svelte-routing
svelte-routing copied to clipboard
Access path in other components
Is there any way to access/watch current path in components that are available in all routes for example header. I would like to show different links based on current path.
<Router url="{url}">
<AppHeader>
<div>
<Route path="/welcome" component="{Welcome}" />
<Route path="/login" component="{Login}" />
</div>
</Router>
<!-- AppHeader -->
<header>
<nav>
{#if currentPath != '/login' }
<Link to="/login">Login</Link>
{:else}
<Link to="/welcome">Go Back</Link>
{/if}
</nav>
</header>
Is there any preferred way to day this?
Hi @iamfrntdv!
There is currently no nice way to do this. We could possibly take some more inspiration from Reach Router and give the location
object as a property to the rendered component
, but that would not work in your example.
We could possibly expose createHistory
and createMemoryHistory
and give the Router
a new history
prop, so that you could supply a history of your own that you can read from and listen to, much like the LocationProvider
functionality in Reach Router.
How about creating global state or variable so it will be available everywhere, something like vue-router does?
Interesting. I have very limited experience with vue-router, and I'm not exactly sure what behaviour you are referring to. Could you elaborate?
Vue Router creates global object/state (accessible everywhere) which updates every time path changes. Here you can see what else is available:
in this case it shows what is current active path and what name, params, queries, meta it has.
@iamfrntdv How about the following approach?
import {getContext} from 'svelte';
import {ROUTER} from 'svelte-routing/src/contexts';
const { activeRoute } = getContext(ROUTER);
$: {
console.log($activeRoute)
}
@kysonic hmmm, this may work. I'll try it and let you know. Thanks.
Thanks @kysonic, your solution works fine for me.
I moved my <navbar>
component to be in scope of the <Router>
<Router>
<NavBar isLoggedIn={isLoggedIn} loggedInUser={loggedInUser} />
<Route exact path="/">
<Home isLoggedIn={isLoggedIn} loggedInUser={loggedInUser} />
</Route>
<Route path="/panels" component={Panels} />
<Route path="/users" component={Users} />
<Route path="/login" component={Login} />
<Route path="*" component={NotFound} />
</Router>
Then on the <NavBar>
component:
<script>
import { getContext } from 'svelte'
import { ROUTER } from 'svelte-routing/src/contexts'
var { activeRoute } = getContext(ROUTER)
...
</script>
<main>
...
{#if !isLoggedIn && ($activeRoute ? $activeRoute.uri : '') != '/login'}
<button type="button" on:click={()=>navigate('/login')}>Login</button>
{:else if isLoggedIn}
<span >{loggedInUser.displayName ? loggedInUser.displayName : ''}</span>
<button type="button" on:click={logout} outline>Logout</button>
{/if}
...
</main>
This way the the login button doesn't get displayed on the <navbar>
when the user is on the \login
route
I have another workaround for when you are in the topmost component, so getContext()
does not work (because you don't have a parent <Router/>
component):
<script>
import {Router, Route} from 'svelte-routing';
import {globalHistory} from 'svelte-routing/src/history';
import {route} from './stores.js';
$route = globalHistory.location;
globalHistory.listen(history => {
$route = history.location;
});
</script>
<Router>
<!-- other routes... -->
<Route path="/" component={Home}/>
</Router>
{#if $route.pathname === '/'}
<img src="logo-home.svg">
{:else}
<img src="logo-general.svg">
{/if}
This way you have the variable $route
in a global store and can access it from anywhere in your app.
@kysonic @henk23 Do these methods still work for you? When I try to use ROUTER context its undefined (I am inside the router context when trying it, in fact have tried moving it all over.)
When I try the globalHistory.listen method I seem to end up with 2 instances of globalHistory and my listener doesn't get called. I don't know how that is even possible.
I have a router embedded in another router, though looking at the code I think this should be fine. If anyone has insight, it'd be appreciated.
I found a solution in case anyone runs into the same issue. It's a bundler problem.
The router was using globalHistory from one place but when I directly imported import {globalHistory} from 'svelte-routing/src/history';
My bundler was grabbing it from a different place. The solution was to add globalHistory to the exports for svelte-routing and import it from there .
Svelte Routing v1.8 has been released, which added useLocation
hook, by using it you can track if location or route changes.
@krishnaTORQUE How can i use the useLocation hook? It does not react to changes and gives me undefined everytime