Reputation: 229
I am trying to convert my vue app to nuxt app. In my vue app I used vue-slick-corousel with ease. But the same code with necessary modifications for nuxt, the corousel is not working on refresh. If I edit the template real time or navigate the app without refreshing the page, it works perfectly on second time visiting the page(s). Here is how I used vue-slick-corousel in my nuxt app
//nuxt.config.js
plugins: [
{ src: './plugins/vue-slick-carousel.js' }
],
Code in the plugin js file:
//vue-slick-carousel.js
import Vue from 'vue'
import VueSlickCarousel from 'vue-slick-carousel'
Vue.component('VueSlickCarousel', VueSlickCarousel)
And finally in the template:
<!-- CustomComponent.vue -->
<template>
<div>
<VueSlickCarousel :arrows="true" :dots="true">
<div v-for="(cat, index) in categories"
:key="index"
style="height: 20px; width: 10px; background-color: red; color: white"
>
{{cat.name}}
</div>
</VueSlickCarousel>
</div>
</template>
<script>
import VueSlickCarousel from 'vue-slick-carousel'
import 'vue-slick-carousel/dist/vue-slick-carousel.css'
// optional style for arrows & dots
import 'vue-slick-carousel/dist/vue-slick-carousel-theme.css'
export default {
name: 'CustomComponent',
data() {
return {
categories: []
}
},
async fetch() {
this.categories = await fetch(
'https://*****************************/categories?limit=20'
).then(res => res.json())
},
components: {
VueSlickCarousel
},
}
</script>
This is the error I am getting on refresh "TypeError: Cannot read property 'length' of undefined"
And whenever I am rendering the page again from clientside, the error goes away. Already tried bounding the container under
<client-only>
tried using a condition
v-if="slik.length"
didn't work. How can I solve this issue?
Upvotes: 0
Views: 2018
Reputation: 46696
EDIT: here is an explanation of the usage of $fetchState.pending
helper.
fetch()
is a non-blocking hook that will allow you to fetch data upon page/component loading
asyncData()
is blocking but only when you navigate and not on initial render which can be annoyingfetch()
and a middleware
VueSlickCarousel
is actually waiting for you to provide it an array of items. But upon initial render and before have fetched any data, you only do have categories: []
as setup in data()
$fetchState.pending
is a handy helper that can tell us when the whole calls in fetch()
are done. So if you will call 4 different APIs, it will equal to false
only when all of the 4 calls will be done.
this.$fetchState.pending = true
but this is forcing it and should be used when understood properly.<VueSlickCarousel v-if="!$fetchState.pending">
, we do basically say wait until all of my things into fetch()
to be done before mounting this component at all. This prevents any .length
method issues because the component itself is not mounted until there is something to apply .length
on.Here is a small image of Nuxt's lifecycle, focused on fetch()
hook.
You should not mix async/await
and then
. Try to only use one of them (I do recommend the first one).
async fetch() {
const response = await fetch(
'https://*****************************/categories?limit=20'
)
const fetchedCategories = await response.json()
console.log('categories', fetchedCategories)
this.categories = fetchedCategories
},
Also, :key="index"
is a bad practice because index
is mutable in a v-for
. Try to use an UUID from the API instead.
I'm pretty sure that those are not required neither:
import VueSlickCarousel from 'vue-slick-carousel'
components: { VueSlickCarousel },
Upvotes: 1