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?
React. cloneElement() is useful when you want to add or modify the props of a parent component's children while avoiding unnecessary duplicate code.
createElement is the code that JSX gets compiled or converted into and is used by reacting to create elements. cloneElement is used for cloning elements and passing them new props. This method is used to describe how the User Interface looks. This method is used to manipulate the elements.
Rather than creating a new component instance (if we already have one), sometimes we'll want to copy it or add custom props/children to the component so we can retain the same props it was created with. We can use React. cloneElement() to handle this for us.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With