Home > Blockchain >  Vue 2; DOM not updating to data change and watcher
Vue 2; DOM not updating to data change and watcher

Time:01-11

I have a child component that gets passed a initialCurrentUser prop. This starts from the top parent <App> component, to a child Sidebar, and then finally to grandchild, WindowFavorite.

When the user is not logged in, the variable is null. When they are, it's an object with their properties including favorites which is an array of their favorited entries.

On the <App>, I have:

<template>
<sidebar
    :initial-current-user="currentUser">
    </sidebar>
</template>

...

export default {
    name: "App",
    ...
    data() {
        return {
            currentUser: null,
        };
    },
   methods: {
   ...
   getUser() { // sets this.currentUser on login success}
   }


In <Sidebar>, I'm setting a data prop to the initialCurrentUser, call currentUser, and passing that to the child WindowFavorite.

Then in the watcher on Sidebar, I have:

 initialCurrentUser: {
            handler: function( val ) {
                this.currentUser = val;
            },
            immediate: true
        }

The <Sidebar> DOM elements are reacting to this change. But when I pass to <WindowFavorite>, the loop in the DOM is checking for the favorites property on a null value. Even though the currentUser is being updated (I see it updated in Vue Dev Tools), the DOM still thinks it's null.

template>
  <div>
    
        <div v-for="favorite in currentUser.favorites" :key="favorite.id" >
           

        </div>
      

 
  </div>
</template>

<script>


export default {
    name: "WindowFavorites",
    components: {
        
    },
    data() {
  
        return {
            currentUser: this.initialCurrentUser
        };
    },

    props: {
        initialCurrentUser: {
            default: null,
            type: Object
        }

    },
    
    mounted() {
 
    },
    watch: {
        initialCurrentUser: {
            handler: function( user ) {
                this.currentUser = user;
            }
        }
    },
    computed: {
     
    },
    methods: {

    }
};
</script>


So while the DOM thinks currentUser is null, it's actually:

{
"id":1,
"favorites":[ {id: 1}, { id: 2}]
}

I'm not sure why the DOM isn't being reactive.

To recap, manages the initial change of currentUser. It's passed to <Sidebar>, which then passes that to WindowFavorite. <Sidebar> has a watcher to watch for the prop change and sets its own currentUser data var, and then uses that to pass to ITS child props.

The data seems to be updating throughout the components and shows correctly in the Vue Dev Tools, however, the dom itself still thinks the changing variable is null.

Once a page refresh happens, it grabs the data correctly. Just not on actual javacript data change.

CodePudding user response:

<Sidebar> and its <WindowFavorites> child are rendered immediately before currentUser is set in App.vue, and their initialCurrentUser props are both bound to currentUser, which is initially null. WindowFavorites tries to render its template, referring to currentUser.favorites (where currentUser is null), leading to the error you observed. Even though currentUser is asynchronously updated afterward, the null reference has already occurred, blocking any updates.

One solution is to render WindowFavorites conditionally on currentUser:

<!-- Sidebar.vue -->
<WindowFavorites v-if="currentUser" :initial-current-user="currentUser" />

demo

  •  Tags:  
  • Related