I'm trying to figure out an issue I have with ES6 modules import.
This is a very simplified version of what I'm attempting to do. My current file structure is much more complicated with nested folders.
I have 2 ReactJS components:
/buttons
/MyComponent1.js
/index.js
/texts
/MyComponent2.js
/index.js
/index.js
My files look something like this:
I'm importing the MyComponent2
from the root index.js
file which is the entry-point of my package.
MyComponent1.js
import MyComponent2 from '../../';
export default () => (
<div><MyComponent2 /></div>
);
MyComponent2.js
export default () => (
<div>Hello world</div>
);
My buttons/index.js
and texts/index.js
files export all components in their own folder:
buttons/index.js
export { default as MyComponent1 } from './MyComponent1';
texts/index.js
export { default as MyComponent2 } from './MyComponent2';
And my root index.js
export all my folders to make them publicly available. It's my entry-point:
export * from './buttons';
export * from './texts';
So when I import MyComponent2
in MyComponent1
from the root index.js
file, it's undefined
. When I import it from ./MyComponent2.js
, it's defined. When I import the entire package in another project and import MyComponent2
from the root index.js
file, it's defined.
It's mind-blowing and I don't understand why I can't import MyComponent2
from the root index.js
file.
I need to do that because I have a set of hundred of components nested in different folder and I want to make them all available from this entry-point file.
Can someone tell me what is happening and how to make this possible?
Thanks
Modules in ES6 work only in strict mode. This means variables or functions declared in a module will not be accessible globally. The export keyword can be used to export components in a module. Exports in a module can be classified as follows − Named exports are distinguished by their names. There can be several named exports in a module.
But the time when it can only be used in conjunction with compilers like Babel is over. Meanwhile Node.js also supports the so-called ES6 modules, and in the browser we can use them if we want to. On both use cases, we will have a look at the end of this article.
You can import everything that’s imported by a module like this: You import the default member by giving it a name of your choice. In the following example Logger is the name given to the imported default member: And here’s how you would import non-default members on top of the default one:
Then buttons/MyComponent is rendered; just before it is rendered i manually require components/index and it is now defined so returns some defined value In essence, when your MyComponent1 is trying to import MyComponent2 via the index file, the index file has not been exported yet so it returns undefined.
you can import all the components from the respective component files and then assign them to a variable in the root component and then export all of them as objects.
import MyComponent1 from './buttons/index'
import MyComponent2 from './texts/index'
export {MyComponent1, MyComponent2}
to import this components in another file or project. you could import only one them using object destructuring.
import {MyComponent1} from 'index.js'
import {MyComponent2} from 'index.js'
Okay, took me a while to figure out what is happening. Please take a look at the sandbox i've setup - https://codesandbox.io/s/nk0qmo096j
I've tried to keep the folder/module structure similar to what you've described. Please look through how the folder/modules are structured before you continue reading.
When you run the code in the sandbox, take a look at the console. You'll see something like this -
So let me try to explain why what you're trying to do is not working
buttons/MyComponent
is the first file to be "exported" (since its at the bottom of the dependency chain; Project/index -> components/index -> buttons/index -> buttons/MyComponent)Note that
components/index
has not been exported yet, so it will return undefined
Then buttons/index
is exported, followed by texts/index
Then buttons/MyComponent
is rendered; just before it is rendered i manually require
components/index
and it is now defined so returns some defined value
In essence, when your MyComponent1
is trying to import MyComponent2
via the index
file, the index
file has not been exported yet so it returns undefined. To work around this, you have to require
MyComponent2
from within MyComponent1
's render method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With