Search code examples
vue.jsvue-props

Elements doesn't react to reactive props being changed


I have this code for a "Show Code", which will render the Code Snippet with different props based on the language selected by the user on the Code Header (working fine). image here

<template>
    <div>
        <CodeHeader @language-selected="onLanguageSelected" />
        <CodeSnippet :language="selectedLanguage" :code="getCodeForLanguage(selectedLanguage)" />
        {{ selectedLanguage }} // WORKS
        {{ getCodeForLanguage(selectedLanguage)}} //WORKS

    </div>
</template>
            
<script>
import CodeSnippet from '@/components/atoms/CodeSnippet.vue';
import CodeHeader from '@/components/cells/CodeHeader.vue';

export default {
    name: 'ShowCode',
    components: {
        CodeSnippet,
        CodeHeader
    },
    data() {
        return {
            selectedLanguage: 'html', 
        };
    },
    methods: {
        onLanguageSelected(language) {
            language = language.toLowerCase();
            this.selectedLanguage = language;
        },
        getCodeForLanguage(language) {
            switch (language) {
                case 'html':
                    return '<h1>Oi</h1>';
                case 'css':
                    return '.h1 {}';
                case 'js':
                    return 'console.log(h1);';
                default:
                    return '';
            }
        },
    },
};
</script>

And this is my code snippet:

<template>
    <div class="code-snippet">
      <pre>
        <vue-prism-component :code="code" :language="language"> {{ code }} {{ language }}</vue-prism-component>
      </pre>
    </div>
  </template>
  
  <script>
  import VuePrismComponent from 'vue-prism-component';
  import 'prismjs/themes/prism.css';
  
  export default {
    name: 'CodeSnippet',
    components: {
      VuePrismComponent
    },
    props: {
      code: {
        type: String,
            default: 
            `<h1>Oops! No code found.</h1>\n <p>Sad :(</p>`
            
      },
      language: {
        type: String,
            default: 'html'
      }
    }
  };
  </script>

On the code you can see those works:

{{ selectedLanguage }} // WORKS {{ getCodeForLanguage(selectedLanguage)}} //WORKS

But the Code Snippet doesn't change.


Solution

  • Your code is perfectly valid, so I went digging.

    Looking at the source code for vue-prism-component, I see that props are read into regular variable which should kill their chance at reactivity or ever changing when used in the render function, as setup is run only once per component.

    In fact, there's a Github issue about that.

    If you can, I suggest downgrading to ^1.0.0 until it's fixed.