vue.jsvuetify.jsmaterial-design-iconsvuetifyjs3

Vue/Vuetify says Icon value is undefined or null


I load a list of items from the db which are to be displayed to the user in a list. Each item is of a particular type, and depending on the type, I wish to show an icon next to it.

I've created a component to control the icon that will be shown. The component accepts the type sa a prop and renders the mdi-icon accordingly.

<div v-if="iconName !== ''">
  <v-icon large color="blue-grey darken-2"> 
    {{ iconName }}
  </v-icon> 
  </div>

The value of iconName is provided either while mounting, or as a computed property - I tried both of these.

export default {
  props: ["activityType"],

  data() {
    return {
      iconType: this.activityType, 
      iconName: 'mdi-script-text-outline', 
      iconMapping: {
        learning_material_video: "mdi-video",
        learning_material_quiz: "mdi-head-question-outline",
        learning_material_article: "mdi-script-text-outline",
      },
    };
  },
  methods: {},
  mounted(){
    this.iconName = this.iconMapping[this.iconType]
  },
  computed: {
    // iconName() {
    //   return this.iconMapping[this.activityType]
    // },
  },
};

This renders perfectly fine and I can ignore and continue working on the next component but the error in the console is a bit worrysome.

Uncaught (in promise) Error: Icon value is undefined or null
at ReactiveEffect.eval [as fn] (icons.tsx?ff78:168:1)
at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:167:1)
at ComputedRefImpl.get value [as value] (reactivity.esm-bundler.js?89dc:1101:1)
at Proxy.eval (VIcon.tsx?e5c2:53:1)
at renderComponentRoot (runtime-core.esm-bundler.js?d2dd:893:1)
at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js?d2dd:5098:1)
at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:167:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:394:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:409:1)

This has no effect in how the page looks or works but I'm worried if this might create issues later. I'm hardly 5 days in into Vue and I might be doing something wrong here. Is my code the right way to do it or can it be better?

ps. This is Vuetify-3.


Solution

  • You should use a safety guard:

    <template>
      <div>
        <v-icon large color="blue-grey darken-2">{{ iconName }}</v-icon> 
      </div>
    </template>
    
    <script>
    export default
    {
      name: 'MyCustomComponent',
      props:
      {
        activityType:
        {
          type: String,
          default: ''
        }
      },
      computed
      {
        iconName()
        {
          return {
            learning_material_video: "mdi-video",
            learning_material_quiz: "mdi-head-question-outline",
            learning_material_article: "mdi-script-text-outline",
          }[this.activityType] || 'mdi-script-text-outline';
        }
      }
    }