2

I have a component called SpotifyButton in the components directory that looks like this:

<template functional>
  <b-button pill size="sm" :href="props.spotifyUri" class="spotify-green">
    <b-img-lazy
      src="~/assets/Spotify_Icon_RGB_White.png"
      height="20"
      width="20"
    />
    View on Spotify
  </b-button>
</template>

<script lang="ts">
import Vue from 'vue';

export default Vue.extend({
  name: 'SpotifyButton',
  props: {
    spotifyUri: {
      type: String,
      required: true
    }
  }
});
</script>

I'm able to import and use this in a component in the pages directory like so without any problem:

<template>
    <spotify-button :spotify-uri="artist.uri"/>
</template>

<script lang="ts">
import Vue from 'vue';
import { Context } from '@nuxt/types';
import FullArtist from '@/types/FullArtist';
import SpotifyButton from '@/components/SpotifyButton.vue';

export default Vue.extend({
  name: 'ArtistPage',
  components: {
    SpotifyButton
  },
  async asyncData({ $axios, params, error }: Context) {
    try {
      const artist: FullArtist = await $axios.$get(`/api/artists/${params.id}`);
      return { artist };
    } catch (e) {
      error({ statusCode: 404, message: 'Artist not found' });
    }
  },
  data() {
    return {
      artist: {
        name: ''
      } as FullArtist
    };
  }
});
</script>


However if I try to import SpotifyButton into another component in the components directory in the same way, I get the following errordid you register the component correctly error.

Here is the ArtistPreview component, which is in the components directory:

<template functional>
  <spotify-button :spotify-uri="props.artist.uri"/>
</template>

<script lang="ts">
import Vue, { PropType } from 'vue';
import SpotifyButton from '@/components/SpotifyButton.vue';
import SimpleArtist from '@/types/SimpleArtist';

export default Vue.extend({
  name: 'ArtistPreview',
  components: {
    SpotifyButton
  },
  props: {
    artist: {
      type: Object as PropType<SimpleArtist>,
      required: true
    }
  }
});
</script>

Am I missing something? Why does an import that works perfectly fine in a pages directory component not work in a components directory component?

1
  • 1
    hmm the only thing i see is the <template functional> maybe remove the functional ? Commented Aug 5, 2020 at 13:37

3 Answers 3

4

This was happening because I'm using functional components. It turns out you can't nest functional components without doing some funky workarounds. Here's the GitHub issue with a few solutions.

I went with the first solution, so my ArtistPreview component now looks something like this:

<template functional>
  <spotify-button :spotify-uri="props.artist.uri"/>
</template>

<script lang="ts">
import Vue, { PropType } from 'vue';
import SpotifyButton from '@/components/SpotifyButton.vue';
import SimpleArtist from '@/types/SimpleArtist';

Vue.component("spotify-button", SpotifyButton);

export default Vue.extend({
  name: 'ArtistPreview',
  props: {
    artist: {
      type: Object as PropType<SimpleArtist>,
      required: true
    }
  }
});
</script>
Sign up to request clarification or add additional context in comments.

Comments

0

Go with:

import SpotifyButton from '~/components/SpotifyButton.vue'

With Typescript is better use another approach: Add 'nuxt-property-decorator' and follow his flow.

So, you define your component as follow:

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'

import SpotifyButton from '~/components/SpotifyButton.vue'

@Component({
  components: {
    SpotifyButton
  },
})
class AnotherComponent extends Vue {
  ...
}
export default AnotherComponent
</script>

[Nuxt Property Decorator on Github][1]

I think is important to read the official [Nuxt Typescript documentation][2] to a proper setup.

I hope it helps!


  [1]: https://github.com/nuxt-community/nuxt-property-decorator
  [2]: https://typescript.nuxtjs.org/

2 Comments

I'm getting the same behavior after trying this. What did you think the cause might be?
Never hit your problem, have you ever tried to remove functional from <template>. Which the Vue version?
0

As you're aware, functional components do not support the components property. There are a few workarounds, the ones below worked for me in the past.

You can use inject to avoiding polluting props.

<template functional>
  <div>
    <component :is="injections.components.CoolComponent"></component>
  </div>
</template>

<script>
import CoolComponent from "./CoolComponent.vue";

export default {
  functional: true,
  inject: {
    components: {
      default: { CoolComponent }
    }
  }
};
</script>

Alternatively, you can use JSX.

import CoolComponent from "./CoolComponent.vue";

export default {
  functional: true,
  render (h) {
    return (
      <div>
        <CoolComponent></CoolComponent>
      </div>
    )
  }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.