skip to Main Content

I’m have an issue where buttons and links jitter on state change (when clicking on the "Sign Out" button). I tried both v-if and v-show and the jitter persists.
Video of the issue: https://www.veed.io/view/89672f51-f55c-411c-883f-440b02cfa4de?panel=share
Reproduction: https://stackblitz.com/edit/nuxt-starter-a8hntf?file=app%2Fcomposables%2FuseStoreAuth.ts.

<div>
  <div>
      <button @click="setColorTheme()">
          <IconDarkMode />
      </button>
      <div v-if="!signedIn && !pending">
          <NuxtLink to="/sign-in">
              <span>Sign In</span>
              <IconSignIn />
          </NuxtLink>
      </div>
  </div>
  <div
      v-if="signedIn && !pending">
      <NuxtLink to="/profile">
          <span>Profile</span>
          <IconProfile />
      </NuxtLink>
      <button to="/sign-in" @click="signOut">
          <span>Sign Out</span>
          <IconSignOut />
      </button>
  </div>
</div>

I also have a 300ms delay for signedIn state in signOut function to wait until page transition ends, but jitter still persists.

if (res.ok) {
    const data = await res.json();
    state.successMessage = data.message;
    if (route.path === '/') {
        window.location.reload();
    } else {
        window.location.href = '/';
    }
    setTimeout(() => {
        state.signedIn = data.signedIn;
    }, 300);
}

Looking for a possible solution.

2

Answers


  1. Chosen as BEST ANSWER

    The solution is recommended @Estus Flask in the comments above.

    Regarding the UI element jitter:

    It's "pending" condition that forces the layout to jump. It's not needed there if you need transitions, i.e. either one of these divs with v-ifs should exist in the layout an any moment of time.

    Regarding the buttons changing before page transition starts:

    You need to use separate state for UI that will differ from store.signedIn and use to promises for correct control flow. I.e onSignOutClick = async () => { await store.signOut(); uiSignedIn.value = store.signedIn }. Also, navigateTo and router methods return promises, you may want to await them too.


  2. I think the issue is the button’s element prop "to" with the click event.
    here is an example of logic you should try:

    signOut() {
      try {
        // first handle your logic
        // request logout from server
        // delete cookies and sesion
        // after success push to route and then change signedIn state(if its not a dynamic value)
        router.push("/sign-in");
        signedIn.value = false
      } catch (error) {
        console.log("logout::error", error);
      }
    },
    

    First handle your logout logic, on success you handle the route and other states, don’t use the to="sign-in" if your logic in the click is a asynchronous function.

    I also recommend adding a fade animation, on the button, it will help prevent the jitter.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search