2

I've been having an issue with importing a react class into a container

My file organization is as follows:

├── components
│   ├── Header
│   │   ├── Header.js
│   │   └── index.js
│   └── index.js
├── containers
│   └── HeaderContainer.js
└── index.js

where components/Header/Header.js exports with

export default class Header extends Component {}

components/Header/index.js is

import Header from './Header';
import './Header.scss';

export default Header;

and components/index.js is

export Header from './Header';

and containers/HeaderContainer.js is trying to import with

import { Header } from '../components';

However, this doesn't work, Header is undefined.

If I use import * as components from '../components';, Header is listed, but using components.Header is again undefined.

However, it works perfectly if I instead do

import Header from '../components/Header';

Can anyone explain why the first two methods don't seem to be working? I've done it before this way, and I cannot figure out what I may have changed (admittedly, part of the reason I'm asking is just to type it out a new way and seeing if it helps)

Additionally, I've been able to use

import { Header } from './components';

from an index file in the main directory, which worked perfectly. The issue seems to somehow be with import { Header } from '../components' only

3 Answers3

1

There are two types of export: named and default. Named export should be consumed by using construct like:

import { Header } from '../components';

Default on the other hand should be consumed like:

import Header from '../components';

You can read more here;

Amid
  • 21,508
  • 5
  • 57
  • 54
  • I'm not sure this applies, right? I'm using default imports in the `components/index.js`, and then exporting to named imports – Chris Barry Aug 23 '17 at 13:51
  • Check the syntax of `export` in the link I have provided. You cant write `export Header from './Header';`. My suggestion would be to remove default exports and stick with named ones. It will make your life easier. – Amid Aug 23 '17 at 13:57
  • My issue here is that it does seem to work in another file, it only doesn't work inside the containers directory – Chris Barry Aug 23 '17 at 14:11
1

You probably have a cyclical dependency issue. Consider:

  1. components/index.js starts loading.
  2. It sees it needs containers/HeaderContainer.js, so it suspends.
  3. containers/HeaderContainer.js starts loading.
  4. It sees it needs import { Header } from '../components';, so it suspends.
  5. components/index.js is already loading from step 1, so this step is a no-op.
  6. containers/HeaderContainer.js starts running again.
  7. Since components/index.js is still loading, the imported Header is pointing to a variable that hasn't been initialized yet, like if you did

    console.log(Header); let Header = ...

Babel's behavior in this situation is to make Header undefined. In a real native ES6 module environment, it would throw an exception because Header wasn't initialized yet.

There are two main options to fix this. Either one should help:

  • Import ../components/Header directly to avoid the already-loading components/index.js.
  • Reorder your imports so Header is already initialized in components. e.g.

    export { HeaderContainer } from './containers/HeaderContainer';
    export { Header } from './Header';
    

    to

    export { Header } from './Header';
    export { HeaderContainer } from './containers/HeaderContainer';
    
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Aha! The cyclical dependency thing is definitely it, I've been importing something directly from components which in turn loads containers, which then load components again. Thanks so much for your help, I don't think I'd ever have figured that out. Marked as correct, I'd upvote but... – Chris Barry Aug 23 '17 at 16:53
0

Because the only thing you can omit from the path is index.js

So if you have

import Header from '../components/Header';

It is the same as

import Header from '../components/Header/index.js';

But if you type

import { Header } from '../components';

Interpreter expects that in the file ../components/index.js or it could be just ../components.js if components is a file and not a folder, it will find a named export

export const Header = () => {...}

More about exports

Dmitriy Nevzorov
  • 6,042
  • 1
  • 20
  • 28
  • Yeah, I have an index.js file in components which imports things from the subfolders of `components/` and then exports them, which I don't really understand why its not working the way I expected – Chris Barry Aug 23 '17 at 13:53