Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle React nested component circular dependency? (using es6 classes)

I am using React with Babel (es6). I have a problem to solve a circular dependency between my components.

I am building a menu where we have:

  • ItemFactory
  • ItemFolder
  • ItemGeneric
  • MoreTypesOfItems

ItemFactory simply returns any of the other components, based on the props passed.

The ItemFolder needs to be able to reuse the ItemFactory, to build nested menus items.

ItemFactory component, itemFactory.js (simplified):


// I need ItemFolder
import ItemFolder from './itemFolder'

// import all different items too

...

function ItemFactory (props) {
  switch (props.type) {
    case 'link': return <ItemLink {...props} />
    case 'blank': return <ItemBlank {...props} />
    case 'folder': return <ItemFolder {...props} />
    default: return <ItemGeneric {...props} />
  }
}

modules.exports = ItemFactory

ItemFolder Component, itemFolder.js (simplified):


// I need the itemFactory
import ItemFactory from './itemFactory'
...
Items = props.items.map(item => {
  return <ItemFactory {...item} />
})

module.exports = ItemFolder

As you can see both are requiring each other. This causes some circular dependency problem where I get an empty object.

Any help appreciated : )

like image 248
Kev Avatar asked Feb 22 '16 17:02

Kev


1 Answers

In a dependency circle, the imported items will be resolved to the exported binding which is not yet initialised. This should not cause any problems if you are not immediately using them (like calling the functions).

Your problem might be the use of CommonJs export syntax. The following should work:

// itemFactory.js
import ItemFolder from './itemFolder'
…

export default function ItemFactory(props) {
  switch (props.type) {
    case 'link': return <ItemLink {...props} />
    case 'blank': return <ItemBlank {...props} />
    case 'folder': return <ItemFolder {...props} />
    default: return <ItemGeneric {...props} />
  }
}

// itemFolder.js
import ItemFactory from './itemFactory'
…

export default function ItemFolder(props) {
  let items = props.items.map(item => {
    return <ItemFactory {...item} />
  })
  …
}
like image 133
Bergi Avatar answered Oct 21 '22 23:10

Bergi