skrln
skrln

Reputation: 542

Render object as React Component

In my implementation I pass a reactelement (at least that's what I think) as a prop.

I would like to render this prop as it's own React Component but the browser complains that it is an object.

Code to clarify:

In parent:

render() {
  return <SortableItem {...extraProps} item={React.cloneElement(item, extraProps)} />
}

The item prop contains the element I want to render in SortableItem

In SortableItem render:

I want to do something like this:

render() {
  return <props.item />
}

When I log props.item I get this:

Object {$$typeof: Symbol(react.element), key: "item-5", ref: null, props: 
Object, type: function…}
$$typeof:Symbol(react.element)
key:"item-5"
props:Object
ref:null
type:function _class()

I am confused as to why $$typeof would say this is a react element indeed, but type says it's a function _class() and when I log/render the browser says it's an object.

This is the error I get in the browser when rendering <props.item /> in SortableItem

Fatal Exception:Uncaught Invariant Violation: Element type is invalid: 
expected a string (for built-in components) or a class/function (for 
composite components) but got: object. Check the render method of 
`SortableItem`.(reload cancelled)

Upvotes: 11

Views: 31569

Answers (2)

Harold
Harold

Reputation: 885

The answer to this is that every block of logic you manipulate in the virtual DOM needs to be wrapped in a single container element. You can insert and remove a list of components, but they need to be wrapped in a single element. If you return

return (
  <div>
    <SortableItem {...extraProps} item={React.cloneElement(item, extraProps)} />
  </div>
)

you'll be ok. Vue and Angular have built in template elements for this purpose. I normally make some sort of template component for this purpose in React that is just a div with no margin or padding that can be used to wrap lists of elements.

Upvotes: 1

Vaibhav Singh
Vaibhav Singh

Reputation: 942

Try this,

Approach 1

In parent:

render() {
  return <SortableItem {...extraProps} item={<YourComponent />} />
}

In SortableItem render:

render() {
  return {this.props.item}
}

Approach 2: In parent:

render() {
  return <SortableItem {...extraProps} >
     <YourComponent />
  </SortableItem>
}

In SortableItem render:

render() {
  return {this.props.children}
}

Upvotes: 4

Related Questions