6

Why does Vue 2 throw an error that a prop is not defined when it is statically defined in the parent template?

Note: This error is not thrown if I bring the javascript inside the .vue file's script tag as opposed to importing it.

Error:

Property or method "embedded" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option or for class-based components, by initializing the property. See https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

loader.html

<div class="overlay">
  <div class="loader" v-bind:class="{ embedded }">
    <div class="loader__items">
      <div class="loader__item"></div>
      <div class="loader__item"></div>
      <div class="loader__item"></div>
      <div class="loader__item"></div>
      <div class="loader__item"></div>
    </div>
  </div>
</div>

loader.js

export default {
  props: {
    embedded: {
      default: false,
      type: Boolean,
    },
  },
};

loader.vue

<template src="./loader.html"/>
<script scr="./loader.js" lang="babel"></script>
<style src="./loader.scss" lang="scss" scoped/>

client.js

import Loader from '../../loader/loader.vue';

components: {
   Loader
}

client.html

<loader :embedded="true" />
tony19
  • 125,647
  • 18
  • 229
  • 307
hally9k
  • 2,423
  • 2
  • 25
  • 47
  • What exactly is the error? How are you importing `loader` into `client.js`? – Phil Mar 18 '18 at 01:40
  • @Phil -> Edited – hally9k Mar 18 '18 at 01:54
  • I've tried declaring it in the `data` property but exactly the same error :( – hally9k Mar 18 '18 at 01:56
  • Your code works without warnings: https://jsfiddle.net/quv49nwa/ – acdcjunior Mar 18 '18 at 01:58
  • @acdcjunior The difference is that you're global defining the Loader component against the Vue instance as opposed to importing it. This is not entirely the same as my code. I may consider this approach as a work around though, thanks. – hally9k Mar 18 '18 at 02:18
  • Yeah, I don't have the resources to try to reproduce your case using vue-cli right now, but, anyway, your code seems correct. That's a very weird behavior indeed. – acdcjunior Mar 18 '18 at 02:20
  • I think it may be to do with webpack import cycles. This component is referenced in a lot of places in the code base. trying as a global component. – hally9k Mar 18 '18 at 02:29
  • it works with vue-cli webpack template as well. https://codesandbox.io/s/yp080xo2zz – Jacob Goh Mar 18 '18 at 03:17
  • @JacobGoh Just tried for a while to reproduce in that sandbox. Couldn't repro :( Must be to do with the graph of imports or something. – hally9k Mar 18 '18 at 03:43
  • 1
    Is it maybe to do with the way that vue shares scope for components... If I put it in a script tag then a new instance of component and it's scope for each import of .vue file? As opposed to if I import then all components share the instance in the module system? I'm pretty noob to Vue so I'm still a bit foggy as to how these bits work in contrast to a Redux app. – hally9k Mar 18 '18 at 03:45

1 Answers1

3

Hypothesis:

When importing the loader.js file using the src="./loader.js" in the .vue file's markup the error in the initial question is thrown. This instance of the component object might be being shared between every instance of the loader component, some of which have the embedded prop passed in and some that don't. This could open the door to other calls to the <loader /> constructor over writing the prop's value on instantiation.

Solution:

Switching to an import and export inside the script tag fixes the error:

loader.vue

<template src="./loader.html" />
<script lang="babel">
    import loader from './loader';

    export default loader;
</script>
<style src="./loader.scss" lang="scss" scoped />
hally9k
  • 2,423
  • 2
  • 25
  • 47
  • Nice debugging. What's prompted you to move the `template`, `script` and `style` to external files? Kinda goes against the _"single file"_ aspect of single file components – Phil Mar 21 '18 at 03:49
  • @Phil I'm just not entirely enamoured with single file components in Vue TBH. I much prefer to have a clean separation of concerns, although would be happy to use JSX in the .js file, unfortunately thats not how the project I'm working on has been written. CSS on the other hand I like to have in seperate files. Personal preference I suppose. – hally9k Mar 24 '18 at 04:58