kit icon indicating copy to clipboard operation
kit copied to clipboard

Add Link Option `data-sveltekit-invalidate`

Open lemmon opened this issue 2 years ago • 3 comments

Describe the problem

My client noted that when clicking the same link (user is already on) they expect the page data to reload. I must agree that in certain cases it makes sense. SvelteKit currently does nothing when user is clicking the same link over and over.

Describe the proposed solution

I propose to add data-sveltekit-invalidate link option. When user is navigating on some other page nothign will change from current system. Howerver when user clicks on the same link again and the data-sveltekit-invalidate option is present SvelteKit triggers the page load() function again and SvelteKit treats this action as if user is navigating to another page.

Alternatives considered

I have tried adding on:click event to links:

function handleClick() {
  if (this.href === $page.url.href) {
    invalidate('page:data')
  }
}

This almost works, however the load function runs twice. I asume that one runs for the invalidate event and the other runs for the navigation event.

Another try:

function handleClick() {
  if (this.href === $page.url.href) {
    goto(this.href, {
      replaceState: true,
      invalidateAll: true,
    })
  }
}

This almost works too however invalidating all the resources is not the desired outcome.

Importance

would make my life easier

Additional Information

No response

lemmon avatar Jun 28 '23 08:06 lemmon

I don't think a link option will suffice here - what exactly should be invalidated? If it's not everything but specific things - like in your case - it makes more sense to solve this programmatically. Possibly we need an invalidate option for goto which would allow you to refresh things more granularly. Another possibility is that you add a click handler to the a tag and do preventDefault/stopPropagation on it if the url is the same and do invalidate instead; shouldn't rerun twice then.

dummdidumm avatar Jun 28 '23 11:06 dummdidumm

I agree that this could be done with combination of goto and invalidate functionality. I don't like the syntax for this solution too much. Applying custom click event and overwriting kit's core functionality is't very pretty, in my opinion. Perhaps a tag data-sveltekit-invalidate would re-trigger only page load function but data-sveltekit-invalidate-all or data-sveltekit-invalidate="all" would trigger all the load functions. Or perhaps data-sveltekit-invalidate="/something:something" would run equivalent of running invalidate('/something:something'). With one exception, this event would seem as if user is navigating and the $navigating store would be triggered as well.

It's something to think about. I am personally fine with only limited functionality. No need to overthink it. Limited functionality might be better than none at all.

lemmon avatar Jun 28 '23 13:06 lemmon

Here's my workaround. In the root layout:

let navigationToggle = false

onNavigate(navigation => {
    if (navigation.to?.url.toString() === navigation.from?.url.toString()) {
        navigationToggle = !navigationToggle
    }
})

And then I wrap the part of the layout I want to reload in {#key navigationToggle}{/key}. You probably just want to re-render the page, not the layout, so you'd typically do this:

{#key navigationToggle}
    <slot />
{/key}

steve-taylor avatar Jun 22 '24 09:06 steve-taylor