kit icon indicating copy to clipboard operation
kit copied to clipboard

First `goto()` call after hot reload and page refresh causes destroy-and-mount and state loss

Open rjkip opened this issue 3 years ago β€’ 9 comments

Describe the bug First goto() call after hot reload and page refresh causes a destroy-and-mount and state loss. This state loss and destroy-and-mount can be annoying when developing and the page has heavy initialisation, like network calls and a slippy map in my case.

Logs

–

To Reproduce

  1. Clone https://github.com/rjkip/sveltekit-destroy-and-mount.
  2. Run npm run dev.
  3. Open http://localhost:3000; it redirects to /0. πŸ§› Count Mount! is logged to the console.
  4. Click the button a few times; nothing is logged to the console.
  5. Cause the page to hot-reload by eg. uncommenting the second ++count;.
  6. Refresh the page.
  7. Click the button.
  8. The page's state is lost and πŸ§› Count Destroy! and πŸ§› Count Mount! are logged to the console.

You may to retry a handful of times and play with hot-reloading/refreshing. I reproduced this several times when writing up this bug, but when I tried again before clicking submit the issue wasn't there...

Expected behavior

  1. The button always increments the count on first click without losing state and resetting to 0, and the component stays mounted.

Stacktraces

–

Information about your SvelteKit Installation:

Diagnostics
  • The output of npx envinfo --system --npmPackages svelte,@sveltejs/kit,vite --binaries --browsers

    System:
      OS: Linux 4.19 Ubuntu 20.04.2 LTS (Focal Fossa)
      CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
      Memory: 364.20 MB / 12.39 GB
      Container: Yes
      Shell: 5.8 - /usr/bin/zsh
    Binaries:
      Node: 12.22.1 - /usr/bin/node
      npm: 7.10.0 - ~/.npm-prefix/bin/npm
    Browsers:
      Firefox: 88.0.1
    npmPackages:
      @sveltejs/kit: next => 1.0.0-next.109
      svelte: ^3.34.0 => 3.38.2
    
  • Your browser

    Firefox 88.0 (64-bit)

  • Your adapter (e.g. Node, static, Vercel, Begin, etc...)

    Node

Severity Just annoying, really.

Additional context

–

rjkip avatar May 28 '21 21:05 rjkip

I have the seme problem, I made a simple example with 3 pages and two buttons.

Initially I navigate to the url http://localhost:3000/site/recibos, the page is loaded I can see my __layout is loaded in the network tab: image

Then I click the button that executes the following command:

<button on:click="{() => goto('/site/empresas')}">Empresas</button>

then I see in the network tab that the __layout is loaded again: image

After that subsequent links are working as expected:

<button on:click="{() => goto('/site/legajos')}">Legajos</button>

image

So, after the first click when the __layout is loaded again everything is destroyed and created again, losing the state as @rjkip said.

efreibe avatar Jul 20 '21 03:07 efreibe

I can't reproduce even with goto commented out, can you try and see if this happens with the default vite template?

ignatiusmb avatar Aug 22 '21 14:08 ignatiusmb

i'm experiencing the same behavior than @efreibe first goto() trigger a 'page refresh', subsequent are okay

neckaros avatar Dec 18 '21 10:12 neckaros

This is not only happening with goto(), but with the first click on an <a> element also.

Only happens a single time (first click/goto), after that everything works as expected.

kazzkiq avatar Apr 17 '22 21:04 kazzkiq

I'm also experiencing this issue on <a> elements as mentioned by @kazzkiq.

petebot avatar Apr 18 '22 16:04 petebot

Guys, I have the same problem. Lost state for the first time

mihrich avatar Apr 27 '22 12:04 mihrich

Good news: Just noticed it only happens on dev server.

I've deployed my application with both adapter-static and adapter-node and after build it works as expected (no reloads on first goto() or <a> click).

So it seems like this bug happens only on development, no issues with production builds.

kazzkiq avatar May 16 '22 15:05 kazzkiq

Good news: Just noticed it only happens on dev server.

I've deployed my application with both adapter-static and adapter-node and after build it works as expected (no reloads on first goto() or <a> click).

So it seems like this bug happens only on development, no issues with production builds.

I don’t think so! I have version SvelteKit v1.0.0-next.338 and I still have the state reset for the npm run dev and npm run preview commands Do pages with the same content count as different pages? For example, there are the following routes: page and page/id If I go from page /page to /page/id using goto(/page/${id}) then the first time my state is reset. Subsequent transitions work without resetting the state.

mihrich avatar May 24 '22 09:05 mihrich

@Rich-Harris i saw you put the need clarification label. How can we help? @efreibe maybe you can put your simple exemple on a repo?

neckaros avatar Aug 05 '22 23:08 neckaros

After upgrading my app to the new routing and the lastest sveltkit 1.0.0-next.524, I am seeing this issue.

It only occurs after the node server restarts and then on the first goto, you get a full page refresh. After that, you can load the site on new tabs etc and it works fine until you restart the node server again.

Definitely an initialization issue, maybe Vite related etc... Anyone have a workaround?

bosticka avatar Oct 24 '22 14:10 bosticka

More testing and I realized that this only happens when I goto a routeId that is importing a new component.

If I called goto to a routeId that was simple html, no problem. But importing that first component for the first time was causing the reload.

My workaround is to pre cache my main route components before I call goto by just importing them in the main +layout.svelte.

bosticka avatar Oct 24 '22 15:10 bosticka

This isn't a bug, it's just how HMR works. If you edit a component, any instances of that component (and their children) will be destroyed and replaced with the new one. State preservation only applies to sibling/parent components β€” attempting to preserve state within a component that you're editing is a fool's errand, and leads to far more confusing/unwanted behaviour than remounting.

Rich-Harris avatar Mar 07 '23 15:03 Rich-Harris

But this issue is about the first goto call after a page reload, with the reload itself being after an HMR change, causing an additional destroy and remount. Why would HMR need to destroy and remount a component that already has the latest changes applied thanks to the page reload?

FeldrinH avatar Mar 07 '23 15:03 FeldrinH

I just checked and I can reproduce the original issue using a pre 1.0 version of SvelteKit, however, after updating to SvelteKit 1.10.0 (latest at the time of writing), I cannot seem to reproduce the issue. It is possible that the issue has been fixed in one of the newer versions of SvelteKit. As pointed out in the original post, there seems to be some element of luck involved in getting the issue to occur, so I wouldn't say that the issue is definitely fixed.

FeldrinH avatar Mar 07 '23 16:03 FeldrinH