Uncaught (in promise) TypeError: Cannot read property 'catch' of undefined - vue.js

I am trying to use vue3.0.0 lazy loading in component but getting some warning.
I get this error when i want to get that specific component inside parent component. I mean as i click to show the child component i amm gettign following error. Under the error i've added my code. please help me. I am not very expert in.
runtime-core.esm-bundler.js?5c40:38
[Vue warn]: Unhandled error during execution of setup function
at <AsyncComponentWrapper key=0 >
at <Profile onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy {…} > >
at <RouterView>
at <App>
runtime-core.esm-bundler.js?5c40:38
[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 <AsyncComponentWrapper key=0 >
at <Profile onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< Proxy {…} > >
at <RouterView>
at <App>
This error also
runtime-core.esm-bundler.js?5c40:2492
Uncaught (in promise) TypeError: Cannot read property 'catch' of undefined
at load (runtime-core.esm-bundler.js?5c40:2492)
at setup (runtime-core.esm-bundler.js?5c40:2574)
at callWithErrorHandling (runtime-core.esm-bundler.js?5c40:155)
at setupStatefulComponent (runtime-core.esm-bundler.js?5c40:7161)
at setupComponent (runtime-core.esm-bundler.js?5c40:7117)
at mountComponent (runtime-core.esm-bundler.js?5c40:5115)
at processComponent (runtime-core.esm-bundler.js?5c40:5090)
at patch (runtime-core.esm-bundler.js?5c40:4684)
at patchBlockChildren (runtime-core.esm-bundler.js?5c40:4999)
at patchElement (runtime-core.esm-bundler.js?5c40:4960)
My code is like
<template>
<div class="profile">
<button #click="show = true"> show lazy loading</button>
<Lazy v-if="show" />
</div>
</template>
<script>
import { defineAsyncComponent, ref } from 'vue'
const Lazy = defineAsyncComponent(() => {
import('../../components/frontend/Lazy.vue')
})
export default {
components: {
Lazy
},
setup(){
const show = ref(false)
return { show }
}
}
</script>
I am also using lazy loading in route level
{
path: '/profile/:id',
name: 'Profile',
component: () => import('../views/frontend/Profile.vue')
}

defineAsyncComponent's callback needs to return a Promise of the imported component definition, but it currently returns nothing:
const Lazy = defineAsyncComponent(() => {
import('../../components/frontend/Lazy.vue')
// ❌ returns nothing
})
You could either add the return statement in the callback:
const Lazy = defineAsyncComponent(() => {
return import('../../components/frontend/Lazy.vue')
})
...or remove the curly brackets for an implicit return:
const Lazy = defineAsyncComponent(() => import('../../components/frontend/Lazy.vue'))

Related

Missing required prop: "value" on model/value binding for custom input component in Vue

I followed this guide while trying to make a custom form component in Vue 3 (composition api, script setup mode).
When I load the page containing my component, I get a console warning like this one:
[Vue warn]: Missing required prop: "value"
at <SwitchControl key=0 name="question-8" model=undefined ... >
My component (CSS omitted):
<template>
<input ref="switchElement"
v-bind="$attrs"
class="gui-switch"
#input="value = !value; emit('update:modelValue', value)"
type="checkbox"
role="switch"
:value="value" />
</template>
<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"
const props = defineProps<{
value: boolean | undefined,
}>()
const emit = defineEmit<{
(e: "update:modelValue", value: boolean | undefined): void,
}>()
const switchElement = ref<HTMLInputElement>()
onMounted(() => switchElement.value!.indeterminate = true)
</script>
The page that contains it uses it like so:
<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
:model="feedbackData[`question-${question.id}`]"
:id="`question-${question.id}`" />
I've tried various things such as changing the name of the emitted event to input or using v-model instead of :model but I haven't managed to fix this yet and I don't know what else to try.
EDIT:
Editing the component to use modelValue thusly:
<template>
<input ref="switchElement"
v-bind="$attrs"
class="gui-switch"
#input="modelValue = !modelValue; emit('update:modelValue', modelValue)"
type="checkbox"
role="switch"
:value="modelValue" />
</template>
<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"
const props = defineProps<{
modelValue: boolean | undefined,
}>()
const emit = defineEmit<{
(e: "update:modelValue", value: boolean | undefined): void,
}>()
const switchElement = ref<HTMLInputElement>()
onMounted(() => switchElement.value!.indeterminate = true)
</script>
Parent:
<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
v-model="feedbackData[`question-${question.id}`]"
:id="`question-${question.id}`" />
Leads to an outright error:
[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 <SwitchControl key=0 name="question-8" modelValue=undefined ... >
Uncaught (in promise) TypeError: invalid 'instanceof' operand type
assertType runtime-core.esm-bundler.js:1877
validateProp runtime-core.esm-bundler.js:1841
validateProps runtime-core.esm-bundler.js:1817
initProps runtime-core.esm-bundler.js:1548
setupComponent runtime-core.esm-bundler.js:6500
mountComponent runtime-core.esm-bundler.js:4206
processComponent runtime-core.esm-bundler.js:4182
patch runtime-core.esm-bundler.js:3791
mountChildren runtime-core.esm-bundler.js:3975
EDIT2:
I managed to zoom in on whereabouts the problem is, but I still can't quite figure out what's happening.
I changed the component so that #input is now #input="emit('update:modelValue', !modelValue)". I'll include the relevant parts of the <script> of the page that includes it:
import SwitchControl from "#/components/SwitchControl.vue"
import type { FeedbackQuestion } from "#/utils/api/story"
import { defineProps, ref } from "vue"
const props = defineProps<{
questions: {id: number}[],
}>()
const defaultModelValues = {
// These are hard-coded for debugging, ideally I'd want it to work with an empty initial object
"question-8": null,
"question-11": null,
}
const feedbackData = ref<Record<string, any>>(defaultModelValues)
Now the symptoms:
When the code looks like the above, with the prop and emit defined as boolean | undefined, I get the following error and the whole for loop is not rendered:
[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 <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8" ... >
Uncaught (in promise) TypeError: invalid 'instanceof' operand type
If instead I annotate the prop and emit as just boolean, the elements load, and I only get a warning (see below). If I then try to change the value by clicking on the element, I keep getting the same warning and the value doesn't change at all, instead of alternating true and false as would be expected. The value attribute in the HTML if I inspect it, does behave correctly (is "" initially, then alternates between "true" and "false").
[Vue warn]: Invalid prop: type check failed for prop "modelValue". Expected Boolean, got Null
at <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8" ... >
In the child component you should define value as modelValue :
<input ref="switchElement"
...
:value="modelValue" />
</template>
.....
const props = defineProps<{
modelValue : boolean | undefined,
}>()
and in parent use v-model instead of :model :
v-model="feedbackData[`question-${question.id}`]"
use ref from vue can fix warning message
import { defineStore } from "pinia";
import { ref } from "vue";
export const usePosts = defineStore("posts", {
state: () => {
return {
data: [],
errors: [],
title: "",
content: "",
image: ref(),
};
},
});
vue file
<q-file color="primary" v-model="postsStore.image" label="Image">
<template v-slot:prepend>
<q-icon name="cloud_upload" />
</template>
</q-file>

How to pass ref as prop: [Vue warn]: Invalid prop: type check failed for prop "containerRef". Expected Object, got HTMLDivElement?

I have this template within parent component:
<template>
<div>
<div
contenteditable
ref="editorContainer"
><editor-content :container-ref="$refs.editorContainer" /></div>
</div>
</template>
I have this props declaration within "editor-content" component:
props: {
//...
containerRef: {
type: Object,
}
},
but I get this warning:
[Vue warn]: Invalid prop: type check failed for prop "containerRef".
Expected Object, got HTMLDivElement
What should be the type of the ref passing as a prop?
To allow only <div> elements, use type HTMLDivElement.
To allow any element, use type HTMLElement.
To allow anything, set type to null or undefined (that way the linter won't issue a warning).
Here is a full example with TypeScript and Nuxt with SSR.
Added more context via comments.
<script lang="ts">
import { defineComponent, PropType, toRef, watchPostEffect } from '#nuxtjs/composition-api'
export default defineComponent({
props: {
element: {
// When using Nuxt SSR, use this otherwise you get error
// This allows any HTMLElement type, if want HTMLDivElement just change it
type: (process.server ? Object : HTMLElement) as PropType<HTMLElement>,
// let's make it explicit that it does not exist from the begining
default: undefined,
},
},
setup(props) {
// Because it can be undefined, let's use `toRef` instead of `toRefs`
const element = toRef(props, 'element')
// Optional Effect example
watchPostEffect((onInvalidate) => {
// This never happens, on post effect all refs are resolved
if (!element.value) return
// Your event listener
const onScroll = (e: Event) => console.log(e)
// Add event listener
element.value.addEventListener('scroll', onScroll, { passive: true })
// Remove event listener
onInvalidate(() => element.value.removeEventListener('scroll', onScroll))
})
},
})
</script>

The object sent as prop is undefined while testing a Vue SFC with Jest

I want to test a Vue single file component which receives a prop as input. When I mock the prop, which is an object, I get an error that the object is undefined, The error comes from the HTML where the values of the object are used. If I make the prop to be a string for example (and I remove answer.value and :class="{'active': answer.selected}" from HTML), everything works fine.
Component:
<template>
<div class="answer-container" #click="setActiveAnswer()" :class="{'active': answer.selected}">
<div class="answer">
<p>{{answer.value}}</p>
</div>
</div>
</template>
<script>
export default {
name: 'Answer',
props: {
answer: Object,
},
methods: {
setActiveAnswer() {
this.$emit('selectedAnswer', this.answer);
}
}
}
</script>
Test file:
import { mount } from '#vue/test-utils'
import Answer from './../../src/components/Answer'
describe('Answer', () => {
it('should receive "answer" as prop', () => {
const answer = {
value: 'testAnswer',
selected: true
};
const wrapper = mount(Answer, {
propsData: {
answer: answer
}
});
expect(wrapper.props().answer.value).toBe('testAnswer');
})
})
The error I get is:
TypeError: Cannot read property 'selected' of undefined
Please advise what am I doing wrong. Thanks!
I managed to fix this by adding a v-if="answer" on <div class="answer-container" ..., which is quite strange (as this is not async data) since the code works fine when checking the application in the browser - the problem only appeared while unit testing the component. I suppose there is also a fix in a Jest/Unit testing way, something like declaring the prop after the component finished rendering/mounting...

how to get param from url and display it in vue

I have an url:
http://localhost:8080/Currency?currency=RMB
I want to get the currency param which is RMB
In:
created(){
this.currencyParam = this.$route.query.currency;
console.log(curr: ${this.currencyParam});
}
and I can get the curr: RMB in F12 - console but in F12 -Vue I get currency:undefined
In my template:
<template v-else>
<gateway
:currency="this.$route.query.currency"
/>
</template>
I get an error:
Error in render: "TypeError: Cannot read property '$route' of undefined found in and in F12 -Vue I still get currency:undefined
You can add a watch property that will allow you to listen changes in query param
data () {
return {
currencyParam = null
}
},
watch: {
'$route.query.currency': function () {
if(this.$route && this.$route.query.currency) { // if not undefined
console.log(`curr: ${this.$route.query.currency}`);
this.currencyParam = this.$route.query.currency;
}
}
}
Also change your template like this;
<template>
<gateway v-if="currencyParam" :currency="currencyParam" />
</template>

Vue.js. Error in the conditional rendering. Property or method is not defined on the instance but referenced during render

Following code produces an error. I want to have a conditional rendering regarding to receiving event. I have a EventBus in the main.js
window.eventBus = new Vue({})
and somewhere in code:
window.eventBus.$emit('change-visibility', true)
I expect to trigger visibility of the next Vue component:
<template>
<div>
<div v-if="viz.isVisible">
<h2>VISIBLE</h2>
</div>
<div v-else>
<h1>NOT VISIBLE</h1>
</div>
</div>
</template>
<script>
export default {
name: 'test',
date() {
return {
viz: {
isVisible: false
}
}
},
created() {
const self = this;
window.eventBus.$on('change-visibility', status => {
console.log('RECEIVED EVENT', status)
self.setVisability(status)
}),
},
methods: {
setVisability(ok) {
console.log('SET VISABILITY-----------------', ok)
this.viz.isVisible = ok
}
}
}
Error:
[Vue warn]: Error in event handler for "change-visibility": "TypeError: undefined is not an object (evaluating 'this.viz.isVisible = ok')"
You have a typo: The method returning the data should be named data(), but you named it date().
Due to the wrong name, no data members are defined for the vue component, and thus this.viz is undefined, which is why the error message claims that this.viz being undefined is not an object, which it would have to be to have a member isVisible.