mefechoel / svelte-navigator

Simple, accessible routing for Svelte
Other
504 stars 39 forks source link

Allow preprocessing (as a Promise) to run before any navigation #7

Closed ghost closed 4 years ago

ghost commented 4 years ago

Is your feature request related to a problem? Please describe. No.

Describe the solution you'd like

Something like:

import * as navigator from 'svelte-navigator';
navigator.beforeNavigation((route, location) => new Promise);

This will alow something like a progress bar. I also don't want the current route content to be empty while progressing.

Describe alternatives you've considered

mefechoel commented 4 years ago

Hey, so here are my thoughts:

I don't really want to extend the api in this way, because we would need a global configuration for this to work. It would not work when using two Routers side by side, which I find is a very useful feature.

But I can definitely see your use case there. You could consider displaying a loading sceleton, similar to the way youtube shows empty video cards, when you enter the website. If you really want to wait for a Promise to resolve though, I suggest you make a custom Link component that works something like this:

<!-- CustomLink.svelte -->
<script>
  import { useNavigate, useResolve, useLocation } from 'svelte-navigator';

  export let to;
  export let beforeNavigation = null;

  const navigate = useNavigate();
  const resolve = useResolve();
  const location = useLocation();

  $: href = resolve(to, $location);

  const handleClick = async e => {
    e.preventDefault();
    if (beforeNavigation) {
      await beforeNavigation($location);
    }
    navigate(to);
  };
</script>

<a {href} on:click={handleClick}>
  <slot />
</a>

Announcement: Promise is not waited before navigation.

Yes, the a11y.createAnnouncement prop does not wait on the returned Promise before navigating, it just awaits before making an announcement.

The lazy loading example isn't working on this regard and it replaces the current route content immediately.

Are you trying the example in the REPL? In the REPL dynamic imports (the import("some/path") function) do not behave like they would in a real App. The REPL packages the dynamically imported scripts right away, as though they were statically imported. That's why no scripts are downloaded. You can clone the repo and try the example in your browser, for a more obvious effect. I don't think there is a way to actually dynamically load it in the REPL. But it sure is confusing. I might add a comment to clarify the issue.

I hope this helps :)

mefechoel commented 4 years ago

I've updated the lazy loading example in the REPL, so it artificially delays component loading. Now we can see the lazy loading in action.

ghost commented 4 years ago

Thanks for the idea, I think a custom link makes sense.