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.
11
The solution is recommended by @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
androuter
methods return promises, you may want to await them too.
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.
3