mefechoel / svelte-navigator

Simple, accessible routing for Svelte

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Navigate to another page without unmounting the current one

ClementNerma opened this issue · comments

Hi there!

I've been using svelte-navigator for a while now, and it's been pretty great so far!

I'm currently having an issue with the way routes are handled though ; to put it simply, there is a page in my application that loads quite a bunch of data, and this takes a while to load.

What I'd like to do is, when the user leaves this page to go to another (all navigation happens through the provided navigate() function), this one isn't unmounted, so when the user goes back to it it loads instantly.

Is that possible? And if so, how?

Thanks in advance for your help!

Hey there!
Each Svelte Navigator router always renders one route exclusively and unmounts it once another route is matched. So keeping a route component mounted after leaving that route is not possible. But there are a couple of ways to solve your problem that you can try.

First, it might be possible to move the data you don't want to loose out of your route component. Depending on your setup you might be able to stick that data into a store, that lives in its own file and just read/write from/to that store from your component. That would make that state somewhat global though, but from your description it sounds like that's kind of what you want. Another possibility might be to wrap your app with a kind of cache component, that exposes a store via context, and use that component to hold the data you need. That wouldn't be quite as "global" as the first suggestion, since you'd still be free to unmount that cache component.

If that is not helpful, there are still ways Svelte Navigator could help. You could use the useMatch hook instead of a Route component, to take care of the url matching. That would look something like this:

<!-- App.svelte -->
<Router>
  <!-- We'll create a custom route component -->
  <MyRoute path="my/path" />
  <Route path="other/path"> ... </Route>
</Router>

<!-- MyRoute.svelte -->
<script>
  import { useMatch } from "svelte-navigator";

  // We'll mimic the path prop from the regular Route component, so the paths can be
  // managed in the same place
  export let path;

  // We'll implement the matching ourselves here, so we can show and hide the
  // component without unmounting it.
  // Note, that the path is static. When the path prop changes it doesn't reflect in the match
  const match = useMatch(path);

  // When match is not null the route matches
  $: isActive = !!match;

  // Do your data fetching and the rest of the component logic ...
</script>

<style>
  /* Hide the component using css instead of unmounting it */
  .inactive {
    display: none;
  }
</style>

<div class:inactive={!isActive}>
  ...
</div>

That way the component is always mounted. Since your taking the matching in your own hands, you're not benefiting from Svelte Navigator's a11y features any more, so you might need to do something manually there to match that behaviour.

For the first solution this is unfortunately not possible as the component must never be unmounted, it is important that all DOM elements remain the same, so everything is exactly like before including the scroll position on the page. Basically I have an infinite scroll page and when going back I need to let the user back exactly where they left.

For the second one I don't think this is possible as every page uses a template which I wrap all the routes in, so it would be quite hard to do.

So I don't think I can do what I want with this library, which means I'll probably use a store to put all informations about the existing DOM elements and scroll position on the page, and restore them afterwards.

Thanks for your help!

commented

I have exactly the same issue, @ClementNerma did you managed to solve it? I would appreciate if you show an example.

I have exactly the same issue, @ClementNerma did you managed to solve it? I would appreciate if you show an example.

I didn't, I worked around that problem and the routes all reload entirely every time.
One thing I did to optimize was to cache the network requests (I make GraphQL requests with Apollo).

commented

That's sad. Do you know if this was solved in SvelteKit?

Sorry I have no idea, I don't use SvelteKit. But I think it's exclusively related to the router, so it depends on the router SvelteKit uses I guess?