Reputation: 5452
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
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.
// 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
// 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 : )
Upvotes: 16
Views: 38919
Reputation: 665040
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} />
})
…
}
Upvotes: 12
Reputation: 39212
One way is to have the individual components inject themselves into the ItemFactory
. This has the advantage of making the factory more easily extended with new types:
const components = {};
export function registerComponent(name, Component) {
components[name] = Component;
};
export default function ItemFactory(props) {
const C = components[props.type];
return <C {...props} />;
}
// ItemFolder.js
import {registerComponent}, ItemFactory from 'itemFactory';
export default class ItemFolder {
...
};
registerComponent("folder", ItemFolder);
Upvotes: 9