Olga B
Olga B

Reputation: 513

Vue.js: Element is shown for a moment despite of conditional rendering

I have a navigation with a button which toggle a menu and a button of signin.

When a user is not authorised, he can see only SignIn button. When the user is signed in, that button disappears and he/she can see a hamburger button which toggle the user's menu.

I have a condition based on the attribute isLoaded which can be false or true depenending on API response (is profile data loaded or not which happens after signin). It works properly but the button SignIn appears for a moment when I reload the page and after redirect to the main page after signin process. I wonder how I can avoid this.

I suspect that this button is shown while the app is waiting for API response and as soon as it sees isLoaded: true, it hides the button after checking the condition.

Here is my code:

<v-toolbar app fixed dark color="light-blue lighten-2">
  <user-nav-button v-if="getProfile.isLoaded"
                   @toggle-drawer="$refs.drawer.drawer = !$refs.drawer.drawer" />
  <v-toolbar-title v-if="getProfile.isLoaded">
    <router-link :to="{ name: '/' }"
                 class="white--text" >
      APP
    </router-link>
  </v-toolbar-title>
  <v-spacer></v-spacer>
  <router-link :to="{ name: 'login' }"
               class="sign-in-button"
               v-if="!getProfile.isLoaded">
    SIGNIN
  </router-link>
</v-toolbar>
<profile-sidebar v-if="getProfile.isLoaded"
                 ref="drawer" />

<script>
export default {
data() {
 return {
  drawer: '',
 };
},
components: {
  UserNavButton,
  ProfileSidebar,
  MainFooter,
 },
 created() {
  this.loadProfile();
 },
 computed: {
  ...mapGetters(['getProfile']),
 },
 methods: {
  ...mapActions(['loadProfile']),
 },
};
<script>

My store:

export default {
 state: {
 profile: {
  isLoaded: false,
  data: [],
  },
},
actions: {
 loadProfile({ commit }) {
  if (config.token !== '') {
    http
      .post('api')
      .then(({ data }) => {
        commit('SET_PROFILE', data);
      });
  }
 },
},
mutations: {
 SET_PROFILE(state, data) {
  state.profile = {
    isLoaded: true,
    data,
  };
 },
},
getters: {
 getProfile(state) {
  return state.profile;
  },
 },
};

Upvotes: 1

Views: 490

Answers (1)

Katinka Hesselink
Katinka Hesselink

Reputation: 4183

Your button is doing exactly what you're telling it to.

  <router-link :to="{ name: 'login' }"
               class="sign-in-button"
               v-if="!getProfile.isLoaded">

When getProfile.isLoaded is false, you're showing it. And that is also your default state.

Personally I would decouple the isloaded from the profile data. Use a loadingfinished data property (or $store property)

What you really want is to show that button only when two conditions are met:

  1. loading is finished

  2. you know that the user is NOT signed in.

Upvotes: 2

Related Questions