Vue warn: 'Unknown custom element' with re-exported component - vue.js

I have an index.js file in my Vue project's components folder which allows me to import components like this:
import { home, search, tour } from '#/components';
The index.js file:
export { default as home } from './home/home.vue';
export { default as search } from './search/search.vue';
export { default as tour } from './tour/tour.vue';
export { default as tourItem } from './tour-item/tour-item.vue';
Now, when doing this with nested components (a component that should be used in another) it gives me the unknown custom element error.
I don't get why that error is thrown - it's just another component, right?
To be more clear, this works:
import tourItem from '#/components/tour-item/tour-item.vue';
And this doesn't:
import { tourItem } from '#/components';

I had the same issue. Try export children/local component just BEFORE parent in index.js. This solve problem in my case.
Solution in Vue forum

Related

register dynamic components for vue app in seperate module file

I would like to make a js module file that imports vue component and register there.
and then inherit this component and use it for the app's main component.
I've found similar cases but the thing is, I don't use vue cli.
custom.js
import customMain from '/custom/components/main/main.js';
window.Vue.defineComponent('custom-main', customMain);
and in the app.js
import Main from '/global/components/main/main.js';
var App = createApp({
...
components: {
'global-main': Main,
},
template: `<component :is='mainComponent'></component>`,
computed: {
mainComponent() {
if(this.settings.customComponent){
return 'custom-main';
}else{
return 'global-main';
}
}
is this doable? what should I do to make this work?
is there other alternative way to load components dynamically?
The best approach for this case is defining a plugin named registerComponents in the plugins folder : plugins/registerComponents.js
import customMain from '/custom/components/main/main.js';
export default {
install: (app, options) => {
app.component('custom-main', customMain);
}
}
in App.js use the plugin:
import registerComponents from './plugins/registerComponents'
var App = createApp({....})
App.use(registerComponents)

Vue2 how export multiple components as library that use Vuex?

i'm trying to export a Vue.js 2 project as a library containing multiple components.
Using this as example I managed to export a single component.
In my "library" project, I've exported in the main.js:
import TestButton from "#/components/TestButton";
import store from "#/store";
export default {
install(Vue, options) {
if (!options || !options.store) {
throw new Error("Please initialise plugin with a Vuex store.");
}
options.store.registerModule("testLibrary", store);
Vue.component("test-button", TestButton);
}
};
I build it via vue-cli-service build --target lib --name testlib src/main.js
Published on npm via npm publish --access-public
And then imported in another Vue 2 project.
Here in the main.js I've:
[...]
new Vue({
store,
render: (h) => h(App),
}).$mount("#app");
import TestButton from "my-test-library";
Vue.use(TestButton, { store });
And then I can successfully use <test-button></test-button> in whatever component I need, while the Vuex Store has a working "testLibrary" module.
Now the question is how I can export multiple components in the first app and import in the second one.
I've found many example about, such as this one, however I can't get it working.
For example, in the library app I'm trying
import TestButton from "#/components/TestButton";
import AnotherComponent "#/components/AnotherComponent";
import store from "#/store";
export default {
install(Vue, options) {
if (!options || !options.store) {
throw new Error("Please initialise plugin with a Vuex store.");
}
options.store.registerModule("testLibrary", store);
Vue.component("test-button", TestButton);
Vue.component("another-component", AnotherComponent);
}
};
While in the second app I'm trying something like
[...]
import { TestButton, AnotherComponent } from "my-test-library";
But whatever syntax I try it seems like the second app goes in a loop while building and don't work.
Any idea how is this done?

vuejs recursive single file components

Unknown custom element: - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
I have a Sidebar that contains a TreeList that contains TreeNodes that each contain a TreeList.
I have read plenty about other people having problems with this. I have tried solutions such as specifying kebab case names for the components. I have read about this being a problem with namespace and I agree, because I have an example working with all components in a single file. When the components are in separate files the above error occurs when reloading my script using vue CLI. Occasionally and without explanation when saving my file the error goes away and the recursion works again.
Then when it works correctly there is an error when clicking on child nodes.
Cannot read property 'length' of undefined
at simpleNormalizeChildren
Is it something do with vue CLI serve?
I am open to declaring these things in the global namespace except I'm not sure how that would work exactly.
import TreeList from './TreeList.vue'
export default {
name: 'tree-node',
components: {
'tree-list': TreeList
},
...
import TreeNode from './TreeNode.vue'
export default {
name: 'tree-list',
components: {
'tree-node': TreeNode
}
...
import TreeList from './TreeList.vue'
import TreeNode from './TreeNode.vue'
export default {
name: 'Sidebar',
components: {
TreeList,
TreeNode
}
This is probably happening because of the circular referencing between your TreeList and TreeNode components ..
When you look closely, you’ll see that these components will actually
be each other’s descendent and ancestor in the render tree - a
paradox!
To resolve this paradox you can either register your components globally using Vue.component, or you can defer the import of one of your components to a later point (by moving your import to the beforeCreate hook or using async components as demonstrated here) ..
TreeList.vue
export default {
name: 'tree-list',
components: {
'tree-node': () => import('./TreeNode.vue')
}
...
}
With Vue 3, you can use Async Components:
export default {
name: 'tree-list',
components: {
'tree-node': defineAsyncComponent(() => import('./TreeNode.vue'))
}
}
Documentation:
https://v3-migration.vuejs.org/breaking-changes/async-components.html#_3-x-syntax
https://v3.vuejs.org/guide/component-dynamic-async.html#async-components

did you register the component correctly? For recursive components, make sure to provide the "name" option

I configured 'i-tab-pane': Tabpane but report error,the code is bellow:
<template>
<div class="page-common">
<i-tabs>
<i-tab-pane label="wx">
content
</i-tab-pane>
</i-tabs>
</div>
</template>
<script>
import {
Tabs,
Tabpane
} from 'iview'
export default{
name:"data-center",
data(){
return {msg: 'hello vue'}
},
components: {
'i-tabs' : Tabs,
'i-tab-pane': Tabpane
}
}
</script>
Error traceback:
[Vue warn]: Unknown custom element: <i-tab-pane> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <DataCenter> at src/views/dc/data-center.vue
<Index> at src/views/index.vue
<App> at src/app.vue
I have tried in the main.js to global configuration:
Vue.component("Tabpane", Tabpane);
but still do not work.
How to resolve this issue?
If you're using a component within a component (e.g. something like this in the Vue DOM):
App
MyComponent
ADifferentComponent
MyComponent
Here the issue is that MyComponent is both the parent and child of itself. This throws Vue into a loop, with each component depending on the other.
There's a few solutions to this:
 1. Globally register MyComponent
vue.component("MyComponent", MyComponent)
2. Using beforeCreate
beforeCreate: function () {
this.$options.components.MyComponent = require('./MyComponent.vue').default
}
3. Move the import into a lambda function within the components object
components: {
MyComponent: () => import('./MyComponent.vue')
}
My preference is the third option, it's the simplest tweak and fixes the issue in my case.
More info: Vue.js Official Docs — Handling Edge Cases: Circular References Between Components
Note: if you choose method's 2 or 3, in my instance I had to use this method in both the parent and child components to stop this issue arising.
Since you have applied different name for the components:
components: {
'i-tabs' : Tabs,
'i-tab-pane': Tabpane
}
You also need to have same name while you export: (Check to name in your Tabpane component)
name: 'Tabpane'
From the error, what I can say is you have not defined the name in your component Tabpane. Make sure to verify the name and it should work fine with no error.
Wasted almost one hour, didn't find a solution, so I wanted to contribute =)
In my case, I was importing WRONGLY the component.. like below:
import { MyComponent } from './components/MyComponent'
But the CORRECT is (without curly braces):
import MyComponent from './components/MyComponent'
One of the mistakes is setting components as array instead of object!
This is wrong:
<script>
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent',
components: [
ChildComponent
],
props: {
...
}
};
</script>
This is correct:
<script>
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent',
components: {
ChildComponent
},
props: {
...
}
};
</script>
Note: for components that use other ("child") components, you must also specify a components field!
For recursive components that are not registered globally, it is essential to use not 'any name', but the EXACTLY same name as your component.
Let me give an example:
<template>
<li>{{tag.name}}
<ul v-if="tag.sub_tags && tag.sub_tags.length">
<app-tag v-for="subTag in tag.sub_tags" v-bind:tag="subTag" v-bind:key="subTag.name"></app-tag>
</ul>
</li>
</template>
<script>
export default {
name: "app-tag", // using EXACTLY this name is essential
components: {
},
props: ['tag'],
}
I had this error as well. I triple checked that names were correct.
However I got this error simply because I was not terminating the script tag.
<template>
<div>
<p>My Form</p>
<PageA></PageA>
</div>
</template>
<script>
import PageA from "./PageA.vue"
export default {
name: "MyForm",
components: {
PageA
}
}
Notice there is no </script> at the end.
So be sure to double check this.
If you have path to the component (which causes a cycle) to index.js, cycle will be begin. If you set path directly to component, cycle will be not. For example:
// WRONG:
import { BaseTable } from #/components/Base'; // link to index.js
// SUCCESS:
import BaseTable from #/components/Base/Table.vue';
I had this error and discovered the issue was because the name of the component was identical to the name of a prop.
import Control from '#/Control.vue';
export default {
name: 'Question',
components: {
Control
},
props: ['Control', 'source'],
I was using file components. I changed the Control.vue to InputControl.vue and this warning disappeared.
The high votes answer is right. You can checkout that you have applied different name for the components. But if the question is still not resolved, you can make sure that you have register the component only once.
components: {
IMContainer,
RightPanel
},
methods: {},
components: {
IMContainer,
RightPanel
}
we always forget that we have register the component before
This is very common error that we face while starting any Project Vue. I spent lot of time to search this error and finally found a Solution.
Suppose i have component that is "table.vue",
i.e components/table.vue
In app.js
Vue.component('mytablecomp', require('./components/table.vue').default);
So in in your index.blade file call component as
<mytablecomp></mytablecomp>
Just you need to keep in mind that your component name is in small not in large or camel case.
Then my above code will surely work for you.
Thanks
We've struggled with this error twice now in our project with different components. Adding name: "MyComponent" (as instructed by the error message) to our imported component did not help. We were pretty sure our casing was correct, as we used what is in the documentation, which worked fine for the other 99% of our components.
This is what finally worked for us, just for those two problematic components:
Instead of this (which, again, works for most of our components):
import MyComponent from '#/components/MyComponent';
export default {
components: {
MyComponent
}
We changed it to ONLY this:
export default {
components: {
MyComponent: () => import('#/components/MyComponent')
}
I can't find the documentation we originally found for this solution, so if anyone has any references, feel free to comment.
If you are using Vue Class Component, to register a component "ComponentToRegister" you can do
import Vue from 'vue'
import Component from 'vue-class-component'
import ComponentToRegister from '#/components/ComponentToRegister.vue'
#Component({
components: {
ComponentToRegister
}
})
export default class HelloWorld extends Vue {}
Adding my scenario. Just in case someone has similar problem and not able to identify ACTUAL issue.
I was using vue splitpanes.
Previously it required only "Splitpanes", in latest version, they made another "Pane" component (as children of splitpanes).
Now thing is, if you don't register "Pane" component in latest version of splitpanes, it was showing error for "Splitpanes". as below.
[Vue warn]: Unknown custom element: <splitpanes> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
In my case it was the order of importing in index.js
/* /components/index.js */
import List from './list.vue';
import ListItem from './list-item.vue';
export {List, ListItem}
and if you use ListItem component inside of List component it will show this error as it is not correctly imported. Make sure that all dependency components are imported first in order.
This is WRONG:
import {
Tabs,
Tabpane
} from 'iview'
This is CORRECT:
import Iview from "iview";
const { Tabs, Tabpane} = Iview;
In my case (quasar and command quasar dev for testing), I just forgot to restart dev Quasar command.
It seemed to me that components was automatically loaded when any change was done. But in this case, I reused component in another page and I got this message.
Make sure that the following are taken care of:
Your import statement & its path
The tag name of your component you specified in the components {....} block
i ran into this problem and below is a different solution. I were export my components as
export default {
MyComponent1,
MyComponent2
}
and I imported like this:
import { MyComponent1, MyComponent2} from '#/index'
export default {
name: 'App',
components: {
MyComponent1,
MyComponent2
},
};
And it gave this error.
The solution is:
Just use export { ... } don't use export default
In my case, i was calling twice the import...
#click="$router.push({ path: 'searcherresult' })"
import SearcherResult from "../views/SearcherResult"; --- ERROR
Cause i call in other component...
The error usually arises when we have used the Component (lets say VText) but it has not been registered in the components declaration of the Parent Component(lets say Component B).
The error is more likely to occur when using components in a recursive manner. For example using tag=VText in an tag, as importing the component in a such case will result in error from Eslint as the component is not directly being used in the template. While not importing the component will cause an error in the console saying the component has not been registered.
In this case, it is a better approach to suppress the ESLinter on registration line of the Component(VText in this case). This suppression is done through writing // eslint-disable-next-line vue/no-unused-components
Example code is below
<template>
<i18n path="AssetDict.Companies" tag="VText">
<template>
<span class="bold-500">Hi This is a text</span>
</template>
</i18n>
</template>
<script>
import { VButton, VIcon, VTooltip, VText } from 'ui/atoms'
export default {
name: 'ComponentB',
components: {
VButton,
VIcon,
CompaniesModifyColumn,
VTooltip,
// eslint-disable-next-line vue/no-unused-components
VText,
},
}
</script>
I just encountered this. Easy solution when you know what to look for.
The child component was the default export in it's file, and I was importing using:
import { child } from './filename.vue'
instead of
import child from './filename.vue'.
What happened to me was I had correctly registered the component in components but I had another components key defined at the bottom of my component, so I had two components definitions and it looked like the latter one overrode the previous one. Removing it made it work.
I encounter same error msg while using webpack to async load vue component.
function loadVMap() {
return import(/* webpackChunkName: "v-map" */ './components/map.vue')
.then(({ default: C }) => {
Vue.component('ol-map',C);
return C;
})
.catch((error) => 'An error occurred while loading the map.vue: '+error);
}
I found that the then function never executed.
so I reg this component out of webpack import
import Map from './components/map.vue'
Vue.component('ol-map',Map);
Then I could gain the detailed error msg which said I used a var which is not imported yet.
I ran into this problem when:
I had components defined twice.
Used component instead of components.
I hope this helps others.
The question has been answered very well by #fredrivett here, but I wanted to add some context for other encountering the Circular Reference error when dealing with variables in general.
This error happens with any exported object not just components.
Exporting a variable from parent and importing it in a nested child:
🌐 EXAMPLE
<script>
// parent
export const FOO = 'foo';
...
</script>
❌ WRONG
<script>
// child
import { FOO } from 'path/to/parent'
export default {
data() {
return {
FOO
}
}
}
</script>
✅ CORRECT
<script>
// child
export default {
data() {
return {
FOO: require('path/to/parent').FOO
}
}
}
</script>
Note: in case you are dealing with objects you might want to create a global state which might serve you better.
I'm curious to know if this approach makes sense or it's an anti pattern.
In my case the child component name was "ABCChildComponent" and I was referring in the HTML as assuming it to work correctly. But, the correct name should be or . Hence, changed the name to "AbcChildComponent" and referring in the HTML works fine.
WRONG WAY :
import completeProfile from "#/components/modals/CompleteProfile";
export default {
components: completeProfile
};
RIGHT WAY :
import completeProfile from "#/components/modals/CompleteProfile";
export default {
components: {completeProfile} // You need to put the component in brackets
};

Create index file full of exports react-native

Is it possible in react native to create an index file from which you can refer to for imports rather than doing '../../folder/component'?
I have tried a few different methods, including the following:
components folder
-> chat
-> Chat.js
-> dashboard
-> Dashboard.js
-> home
-> Home.js
-> index.js
index.js
import Home from './home/Home'
import Dashboard from './dashboard/Dashboard'
import Chat from './chat/Chat'
module.exports = {
Home,
Dashboard,
Chat,
}
Then inside a component, lets say Dashboard,
import { Home, Chat } from '../components'
Another method:
index.js
export Home from './home/Home'
export Dashboard from './dashboard/Dashboard'
export Chat from './chat/Chat'
I also tried surrounding the export with curlies, ex export { Home } from './home/Home' because the compiler threw an error otherwise, but it still did not work this way.
I also tried the method inside this users question Requiring Modules in react-native
Is this functionality possible in react-native?
Yes, it is possible. Do the following.
Do named exports from Component files.
from Home.js
export { Home };
from Chat.js
export { Chat };
from Dashboard.js
export { Dashboard };
where Home, Chat and Dashboard are the components names in the respective files.
Now in your index.js Do following:
export * from './home/Home';
export * from './chat/Chat';
export * from './dashboard/Dashboard';
use them in other files like this:
import { Home, Chat, Dashboard } from '../components'
Update 1
If you are using redux and want to export the component which is connected to the store, then use the following:
Store the connected component in a const variable like this:
const HomeComponent = connect(mapStateToProps, mapDispatchToProps)(Home)
then export it like this:
export { HomeComponent }