Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"$attrs is readonly","$listeners is readonly","Avoid mutating a prop directly"

I am new to Vue. I am trying to develop a chatting application where friend list will be shown on the left menu and the chat box will be shown at the body. I am loading friend list using an ajax call and routing to chat box based on friend id. Here is the code sample.

<div class="chat-container clearfix" id="chat">
    <div class="people-list" id="people-list">
        <chatlist-component></chatlist-component>
    </div>

    <div class="chat">
       <router-view></router-view>
    </div>
</div> 

chat list component will load friend list from the server. Here is my app.js file;

Vue.use(VueRouter)

const router = new VueRouter({
  routes,
  linkActiveClass: "active"
});


    import ChatComponent from './components/ChatComponent';
    const routes = [
      { path: '/chat/:id/:name', component: ChatComponent , name: 'chat'}
    ];
    Vue.component('chatlist-component', require('./components/ChatlistComponent.vue'));

    const app = new Vue({
        el: '#chat',
        router
    });

And Chat list component template code

<li class="clearfix" v-for="user in users">
                <img :src="baseUrl+'/img/default_image.jpeg'" alt="avatar" class="chat-avatar rounded-circle" />
                <router-link class="about" :to="{ name: 'chat', params: { id: user.id, name:user.name }}">
                    <div class="name">{{user.name}}</div>
                    <div class="status">
                        <i class="fa fa-circle online"></i> online
                    </div>
                </router-link>

            </li>

It works fine until I switch to another user. When I click on any router list from chatlist component it works fine but throws following error to console.

app.js:19302 [Vue warn]: $attrs is readonly.

found in

---> <RouterLink>
       <ChatlistComponent> at resources/assets/js/components/ChatlistComponent.vue
         <Root>

app.js:19302 [Vue warn]: $listeners is readonly.

found in

---> <RouterLink>
       <ChatlistComponent> at resources/assets/js/components/ChatlistComponent.vue
         <Root>

app.js:19302 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "to"

Thanks in advance

like image 676
BlackJack Avatar asked Mar 31 '18 08:03

BlackJack


2 Answers

First, these errors only come out in non-production builds, however they indicate a problem that should be resolved before production release.

The $attrs, $listeners and other warnings are displayed if there's more than one instance of Vue loaded. As I understand it, this can happen usually for one these reasons:

  • it is being loaded/packed into the bundle by webpack and also loaded externally (not via webpack)
  • it is being loaded by something you include (e.g. vuetify, vue-test-utils, vue-cli-electron-builder) one way and by your webpack config another way (e.g. absolute vs relative paths, common.js vs esm.js vue files, runtime-only vue vs compiler+runtime vue)

If you click on that line (it was app.js:19302 in your output above) and put a breakpoint where the message is coming out, you can see the list of modules in the stack traceback to see if there's more than one path to Vue listed. For example, see that the top three modules have a different path below (but are all part of Vue): enter image description here If you see Vue showing up in two or more different ways, it demonstrates that more than one instance of Vue is loaded. Vue only supports a single instance, and can produce these error messages if more than one is loaded.

There are several links to issues included above, the Vuetify issue was the one I filed. In that case, Vuetify requires Vue and was loading it differently than I was. Usually the fix is to check your webpack config where Vue is specified (or isn't) and try to make it match the way the other copy is being included (e.g. absolute vs relative path, or packed vs external).

like image 96
Appurist - Paul W Avatar answered Sep 19 '22 20:09

Appurist - Paul W


This error was happening to me because I was using Git submodules in my project and I had the following folders:

  • ./node_modules - this is for the main project. There was vue installed in these node_modules.
  • ./my_git_submodules/vue_design_system/node_modules - design system that provides basic components (also uses vue). Vue was also installed here!!

So because both:

  • ./node_modules/vue and
  • ./my_git_submodules/vue_design_system/node_modules/vue

existed, running npm run serve (vue-cli-service build underneath) built two instances of Vue. This was a really nasty issue because it broke reactivity in certain cases (ie. you click a button and nothing happens - you just get the $listeners readonly error)

Quick fix:
removing node_modules in the child folder (vue_design_system) and running npm run serve worked for me.

Long term fix:
you'll probably need to make Webpack ignore nested node_modules folders by adding a rule in vue.config.js

like image 38
walnut_salami Avatar answered Sep 20 '22 20:09

walnut_salami