Reputation: 3833
If we have the following structure on a React application:
class BasePage extends React.Component {
render() {
return <div>
{this.props.header}
{/*<Header title={this.props.title} />*/}
</div>
}
}
BasePage.defaultProps = {
header: <header>Base Page</header>
}
class Header extends React.Component {
render() {
return <header>
<h1>{this.props.title}</h1>
</header>
}
}
class TestPage extends BasePage {
}
TestPage.defaultProps = {
header: <Header />
}
class Root extends React.Component {
render() {
return <div>
<TestPage
title="Test Page Title"
/>
</div>
}
}
ReactDOM.render(
<Root />,
document.getElementById('root')
)
If we have a common component like <Header />
we can pass a title property easily like <Header title={this.props.title} />
.
But how can we pass props inside a component if this component is defined as a prop itself?
For example, how can we do something like:
{this.props.header title={this.props.title}}
So it will render the Test Page Title correctly?
Important note: we could overwrite the render method inside the Test component. But the purpose of this question is to solve this problem without doing this.
Upvotes: 4
Views: 4827
Reputation: 662
This seems like a great use case for React.cloneElement
.
React.cloneElement(this.props.header, { title: this.props.title });
It returns a clone of the component with the new props included.
Upvotes: 1
Reputation: 6944
Firstly, props
are read-only and a component should never be update it's own props
, so lines like
componentWillMount() {
this.props.header = <header>Base Page</header>
}
should not be used. defaultProps
can do what I think you are trying to do:
class BasePage extends React.Component {
render() {
return <div>
{this.props.header}
{/*<Header title={this.props.title} />*/}
</div>
}
}
BasePage.defaultProps = {
header: <header>Base Page</header>
}
Secondly, inheritance is not often done in React. I'm not saying don't do what your'e doing, but take a read of the docs and see if there is perhaps a simpler way to achieve the same goals.
Finally, setting props on components passed as props. There are a couple different ways to do this.
If you pass the Component
rather than the <Component />
you can add props like normal:
ChildComponent = (props) => {
const HeaderComponent = props.header
return <HeaderComponent title="..." />
}
ParentComponent = () => <ChildComponent header={Header} />
You can clone the element to override props:
ChildComponent = (props) => {
const HeaderComponent = React.cloneElement(props.header. { title: "..." })
return <HeaderComponent />
}
ParentComponent = () => <ChildComponent header={<Header />} />
NOTE: I have used functional components instead of class components for brevity, but the concepts are the same.
Upvotes: 3