The point of the CALL {} is to allow iteration through the list elements (exposed when you UNWIND, so with each iteration of the subquery the next element of the list will be processed).
So provided that the list ordering is such that the elements that are dependencies are processed earlier in the list, you should be fine.
For example, using your components, assuming that the parts all exist, and that the component dependencies are such that a component only uses components earlier in the list:
theComponents: [
{
id: 'component1',
parts: [ 'part1', 'part2' ]
},
{
id: 'component2',
parts: [ 'part2', 'part3', 'component1' ]
},
{
id: 'component3',
parts: [ 'part3', 'component1' , 'component2']
},
]
You could process like this:
UNWIND $theComponents AS component
CALL {
WITH component
MERGE (c:Component {id:component.id})
WITH component, c
UNWIND component.parts as partId
MATCH (part:Component {id:partId})
MERGE (c)-[:USES]->(part)
}
There's no need for the list because you've already processed all elements of the list.
But if there's something missing about what you're intending to do with this, please clarify.
If you have no guarantee that you'll be processing this with the ordering described, then provided the nested parts list has everything you need to create the node, just use MERGE for that instead of MATCH:
UNWIND $theComponents AS component
CALL {
WITH component
MERGE (c:Component {id:component.id})
WITH component, c
UNWIND component.parts as partId
MERGE (part:Component {id:partId}) // changed from MATCH to MERGE
MERGE (c)-[:USES]->(part)
}