Search code examples
javascriptreactjsjsxreact-functional-component

Objects are not valid as a React child (found: object with keys {type, props}). If you meant to render a collection of children, use an array instead


I am trying to implement React.createElement().But I am getting following error

Uncaught Error: Objects are not valid as a React child (found: object with keys {type, props}). If you meant to render a collection of children, use an array instead.

But when I try original function {React.createElement} mine is {Reacto.createElement} it works but if I log the element returned from Original and mine function they are pretty much same

Here is code

import {createRoot} from "react-dom/client";
import  React from "react";


function createTextElement(text){
    return text
}

function createElement( type , props , ...children ){
    return{
        type,
        props : {
            ...props,
            children : children.map(child =>
                typeof child === "object"
                ? child
                : createTextElement(child)
            ),
        },
    }
}

const Reacto = {
    createElement,
}
//Calling mine function
const element = Reacto.createElement(
    'h1',
    { className: 'greeting' },
    "This is another",
    'Hello'
);
//calling Reacts function
const elementReact = React.createElement(
    'h1',
    { className: 'greeting' },
    'Hello',
    "This is another"
);
//logging both elements
console.log(element);
console.log(elementReact);
const root = createRoot(document.getElementById("root"));
root.render(element)

Here is some logs

This is my element

Object { type: "h1", props: {…} }
​
props: Object { className: "greeting", children: (2) […] }
​​
children: Array [ "This is another", "Hello" ]
​​​
0: "This is another"
​​​
1: "Hello"
​​​
length: 2
​​​
<prototype>: Array []
​​
className: "greeting"
​​
<prototype>: Object { … }
​
type: "h1"
​
<prototype>: Object { … }

This is Reacts element

Object { "$$typeof": Symbol("react.element"), type: "h1", key: null, ref: null, props: {…}, _owner: null, _store: {…}, … }
​
"$$typeof": Symbol("react.element")
​
_owner: null
​
_self: null
​
_source: null
​
_store: Object { … }
​
key: null
​
props: Object { className: "greeting", children: (2) […] }
​​
children: Array [ "Hello", "This is another" ]
​​​
0: "Hello"
​​​
1: "This is another"
​​​
length: 2
​​​
<prototype>: Array []
​​
className: "greeting"
​​
<prototype>: Object { … }
​
ref: null
​
type: "h1"

I dont know whats happening anything will help if you know.


Solution

  • React is specifically looking for the $$typeof property to identify it as being a react element:

    "$$typeof": Symbol("react.element")
    

    Not only does it have to have that property, it has to have one of a few predefined symbols on that property. The symbols aren't exported by react, but you can get them via Symbol.for("react.element") or similar. "react.element" is the most common, but you can see others in this file. You may also need to add other properties to finish fooling react, such as ref: null.

    There's a few spots in the react codebase where they check for $$typeof, but here's one: https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactChildFiber.js#L534 . The exception you're seeing is thrown a few lines later, by this code:

    throwOnInvalidObjectType(returnFiber, newChild);