Reputation: 2078
I have a situation where I want to render a default component, UNLESS a different one is passed in an object.
{map(changes, item => {
const hasChanged = item.fromValue !== item.toValue;
const Component = item.Component;
return (
<div key={uuid.v4()} className="row">
<div className="col-md-6">
{Component ? (
<Component
key={uuid.v4()}
labelColor={hasChanged ? '#AB2912' : ''}
backgroundColor={hasChanged ? '#FFEE7E' : ''}
shouldBoldValue={hasChanged}
label={item.label}
cssClasses="preview-item-padding"
capitalize={false} />
) : (
<SimpleLabelText
key={uuid.v4()}
labelColor={hasChanged ? '#AB2912' : ''}
backgroundColor={hasChanged ? '#FFEE7E' : ''}
shouldBoldValue={hasChanged}
label={item.label}
text={item.toValue}
cssClasses="preview-item-padding"
capitalize={false} />
)}
</div>
</div>
);
})}
In that code above, I want to render SimpleLabelText
unless the item
object has a Component property. Component
is a jsx tag created in a different file.
I don't think it matters, but here is the function that creates the tag in the other file (this is temporary, I'm going to add stuff to it later)
function getCustomComponent(text) {
return (
<SimpleLabelText
text='something'
/>
);
}
However, when I run this, the whole thing explodes and I get this error message;
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: . Did you accidentally export a JSX literal instead of a component?
How can I properly render the jxg tag that is getting assigned to Component
?
Upvotes: 3
Views: 2199
Reputation: 9408
I hope your item.component
is the result of calling getCustomComponent()
. Here you need to notice that getCustomComponent
returns an object and not an function
or class
. So you have to directly render it like {item.Component}
instead of using this -> < />
notation.
Keeping this in mind, your code would transform to something like below.
return (
<div key={uuid.v4()} className="row">
<div className="col-md-6">
{ item.Component ? item.Component : (
<SimpleLabelText
key={uuid.v4()}
labelColor={hasChanged ? '#AB2912' : ''}
backgroundColor={hasChanged ? '#FFEE7E' : ''}
shouldBoldValue={hasChanged}
label={item.label}
text={item.toValue}
cssClasses="preview-item-padding"
capitalize={false} />
)}
</div>
</div>
);
But this does not entirely solve your problem. The props that you need to pass is not getting passed now(in case of item.Component
being present). So you might need to look at React.cloneElement
. You can read about it here https://reactjs.org/docs/react-api.html#cloneelement and some examples online of how to get your props passed to your item.Component
and render the same.
Upvotes: 3
Reputation: 758
Try this
{ () => (Component ? <Component /> : <SimpleLabelText />) }
abbreviated for brevity. The inside of the brackets needs to be a function that returns your component. The other main issue that causes this error message would be from your import statements, so please include that as well.
Upvotes: 2