React.CloneElement returning an object instead of function

10,690

First you need to understand the difference between React component and React element.Both are actually different.

To be specific in jsx, in your case, A is a react component and <A /> is a react element. If you look at the React.cloneElement docs, then it expect an element as a first argument, but here you are passing a component. So first change you need to do is to pass an element to React.cloneElement like this

const newComponent = React.cloneElement(<A />,{
    message: "Hello World"
})

The second thing is that the Route component expects a react component as component prop, but React.cloneElement returns a react element instead of component (that means newComponent is an element, not component). Therefore you cannot just simply export newComponent from the B.js file. You have to export a component instead. For that you can create a class component/stateless component. So your B.js should look something like this

// B.js
import A from "./A"

const newComponent = React.cloneElement(<A />, {
  message: "Hello World"
})

export default class B extends React.Component {
  render() {
    return (<div>{newComponent}</div>)
  }
}

By the way, you don't even need cloneElement here in your case. You can simply return a component from B.js which render A. This is just for understanding purpose.

Share:
10,690
besrabasant
Author by

besrabasant

Updated on June 14, 2022

Comments

  • besrabasant
    besrabasant almost 2 years

    I am having a hard time understanding the behaviour of React.cloneElement() function

    I have my Component Structure something like this

    A.js

    export default class A extends React.Component {
         render() {
             return (<h1>{ this.props.message }</h1>)
         }
     }
    

    B.js

    import A from "./A"
    
    const newComponent = React.cloneElement(A,{
        message: "Hello World"
    })
    
    export default newComponent
    

    C.js

    import B from "./B"
    import { BrowserRouter as Router, Route } from "react-router-dom"
    
    // To Be very precise
     export default class C extends React.Component {
         render() {
             return (
                 <Router>
                    <Route path="/" component={B}  />
                </Router>
             )
         }
     }
    

    But I get this Error

    Invalid prop component of type object supplied to Route, expected function.

    but When I pass Component A directly into the Route component, it renders fine.

    When I console.log Component A inside the render function of Component C, I get a function but When I console.log Component B inside the render function of Component C, I get a object

    What am I missing?