I am getting the following error while creating slides in Vue.js:
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <Anonymous key=1 >
at <Anonymous pager="true" options= {initialSlide: 1, speed: 400} >
at <Anonymous fullscreen=true >
at <IonPage isInOutlet=true registerIonPage=fn<registerIonPage> >
at <Product Details ref=Ref< Proxy {…} > key="/products/1" isInOutlet=true ... >
at <IonRouterOutlet>
at <IonApp>
at <App>
Uncaught (in promise) DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
Uncaught (in promise) DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
at insert (webpack-internal:///./node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js:222:16)
at mountElement (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:3958:9)
at processElement (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:3899:13)
at patch (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:3819:21)
at componentEffect (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:4312:21)
at reactiveEffect (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:71:24)
at effect (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:46:9)
at setupRenderEffect (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:4277:89)
at mountComponent (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:4235:9)
at processComponent (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:4195:17)
If I add the slides hard coded it does not show any errors. But if I add the slides dynamically using a v-for loop then it shows the above errors.
I have added the slides in following way:
This is the template:
<ion-slides pager="true" :options="slideOpts">
<ion-slide v-for="image in product.product_images" v-bind:key="image.id">
<h1>Slide 1</h1>
</ion-slide>
</ion-slides>
This is the script:
export default {
name: "Product Details",
components: {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonSlides,
IonSlide,
},
data() {
return {
product: {},
};
},
setup() {
// Optional parameters to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options.
const slideOpts = {
initialSlide: 1,
speed: 400,
};
return { slideOpts };
},
mounted: function () {
fetch("http://localhost:4000/api/products/" + this.$route.params.id, {
method: "get",
})
.then((response) => {
return response.json();
})
.then((jsonData) => {
this.product = jsonData;
// console.log(jsonData.product_images);
});
},
};
What am I doing wrong in the code?
Arguably, the error message could be improved on this one.
The error was caused by trying to iterate through a non-iterable (in your case
undefined), usingv-for. Specifically, before the call made inmount()returns,product.product_imagesisundefined, because you initiateproductas empty object.Vue 2 style solutions
product.product_imageas iterable:or provide an empty array as fallback in template:
or place a
v-ifon the parent of thev-for:Vue 3 style solution
Make the entire
ProductDetailscomponent suspensibe, by giving it anasync setupfunction. In thesetupfunction, make the call to get the product.Proof of concept:
Now place
<product-details>into a<Suspense>'s<template #default>, providing a fallback template (which will be rendered while<Suspense>resolves all the async components found in its default template):The beauty (and elegance) of using
<Suspense>is that the parent doesn't need to know the actual condition(s) for which the markup is not yet to be rendered. It simply waits for all suspensible components to resolve.In short, using
<Suspense>you no longer need to hardcode the rendering logic into the template usingv-ifs and specifying the condition in clear, on the wrapper. Each async child component contains its own condition and all it announces to the parent is: i'm done. When all are done, they're rendered.