jcoleau
jcoleau

Reputation: 1200

Reactivity issue in vue component

Thanks for reading, I am quite puzzled by this reactivity behavior. I had buttons on a navbar, displayed upon condition in the app component (App.vue):

<button
 type="button"
 v-if="loggedIn()"
 @click="logout"
 class="btn btn-outline-light"
>

with the associated script:

methods: {
   loggedIn() {
     return !(auth.getUser() == null);
   },

here everything works fine and the logout button appears once you log in. Now I am directed to change the design to a sidebar, and create a sidebar component (SideBar.vue) with the exact same html and script. Only issue, the button does not react to the change. the only difference is that the navbar is in the App.vue and SideBar is a component of App like so :

<template>
  <div id="app">
    <div id="nav">
      <nav class="navbar navbar-expand-lg navbar-light ">
        // navbar elements with reactive buttons
      </nav>
      <side-bar />
    </div>
    <main>
     <router-view />
    </main>
  </div>
</template>

Edits : I tried to use a computed property in the component without success. I found a way to make it work by passing a property from the app to the sidebar component but I don't like it as I will have to scale probably later. any ideas? Thanks in advance.

Upvotes: 0

Views: 775

Answers (3)

MiKr13
MiKr13

Reputation: 1511

Use computed property to bind with v-if like this:

computed: {
  loggedIn () {
    return !(auth.getUser() === null)
  }
}

More here: https://v2.vuejs.org/v2/guide/computed.html

Upvotes: 0

Thieu
Thieu

Reputation: 168

I think in general the structure isn't working out here. It's true like some others said that it's better to use a computed property but this is not the issue right here.

Basically, as soon as the app loads you should call auth.getUser(), for example inside your mounted() or created() handler;

// Sidebar.vue or your Root new Vue()
{
    data() {
        return {
            user: null,
        };
    },
    created() {
        this.user = auth.getUser();
    },
}
<button
 type="button"
 v-if="user"
 @click="logout"
 class="btn btn-outline-light">

You can add this to your sidebar component, but it's usually better to handle authentication on the application root component or use Vuex because you often need to know whether or not you're logged in on multiple parts of the app.

If you want to add the created() handler and user variable to your root component you can access it like so;

<button
 type="button"
 v-if="$root.user"
 @click="logout"
 class="btn btn-outline-light">

Upvotes: 1

jcoleau
jcoleau

Reputation: 1200

Computed cannot be used here, a computed property will never update, because return !(auth.getUser() === null)is not a reactive dependency.

In comparison, a method invocation will always run the function whenever a re-render happens. The solution then, is to re-render the side bar as documented by Michael Thiessen:

<side-bar :key="loggedIn()"/>

Upvotes: 0

Related Questions