Reputation: 5234
I found myself writing code like this, for a bunch of components that have some commonality:
class PropertyBlock extends React.Component {
render() {
const { headtext, blockType, selectedId, selectOptions, onChange, extratext } = this.props
return (
<div className='propblk'>
<div className='headline'>{headtext}</div>
{blockType == 'dropdown' ? <PropBlk_Dropdown selectOptions={selectOptions} selectedId={selectedId} onChange={onChange} />
:
blockType == 'inp_line' ? <PropBlk_InputLine value={selectedId} onChange={onChange} />
:
blockType == 'inpstory' ? <PropBlk_InputStory value={selectedId} onChange={onChange} extratext={extratext} />
:
blockType == 'showline' ? <PropBlk_ShowLine value={selectedId} lines={selectOptions} />
:
blockType == 'inp_date' ? <PropBlk_InputDate value={selectedId} onChange={onChange} />
:
blockType == 'inp__chk' ? <PropBlk_Checkbox value={selectedId} onChange={onChange} extratext={extratext} />
:
<div>
{selectedId}
</div>
}
</div>
)
}
}
But somehow I thought that could be better. I was thinking about a parent
component and a lot of specialized child
components that inherit from that parent. like:
class PropBlk_Type1 extends PropertyParentBlock {
...
}
However, reading On React it seems that inheritance should be avoided. So I tried something in line of the React example like this:
class PropertyParentBlock extends React.Component {
render() {
const { headtext, myownhtml } = this.props
return (
<div className='propblk'>
<div className='headline'>{headtext}</div>
{myownhtml}
</div>
)
}
}
class PropBlk_Type1 extends React.Component {
render() {
const { headtext, value, onChange, extratext } = this.props
return (
<PropertyParentBlock headtext={headtext}
myownhtml={(
<div>
<input value={value} onChange={(e) => onChange(e.target.value)} />
</div>
)}
/>
)
}
}
So the specialized html is loaded into the parent component as a property myhtml
. Building this with WebPack gave no syntax errors, and actually running this creates the desired html and it seems to work.
As I am still learning React I am wondering if I am on the right track, or that there are better ways and best practices for this kind of inheritance or composition.
Upvotes: 0
Views: 505
Reputation: 5234
By reading the React doc more closely, I found out that I was on the right track. Only my example could be simplified by leaving out one pair of parentheses and utilize the special props.children
.
I could rewrite the ugly code of the question to something like this 'parent' component:
class PropBlk_Frame extends React.Component {
render() {
const { headtext } = this.props
return (
<div className='propblk'>
<div className='headline'>{headtext}</div>
{this.props.children}
</div>
)
}
}
The above component is used in a number of 'child' components, like:
class PropBlk_InputLine extends React.Component {
render() {
const { headtext, value, inputfield, onChange } = this.props
return (
<PropBlk_Frame headtext={headtext}>
<input value={value} onChange={(e) => onChange(true, e.target.value, inputfield)} onBlur={() => onChange(false, null, inputfield)} />
</PropBlk_Frame>
)
}
}
class PropBlk_InputDate extends React.Component {
render() {
const { headtext, value, inputfield, onChange } = this.props
return (
<PropBlk_Frame headtext={headtext}>
<input type='date' value={value} onChange={(e) => onChange(true, e.target.value, inputfield)} onBlur={() => onChange(false, null, inputfield)} />
</PropBlk_Frame>
)
}
}
Now I can build my web page with the specialized components like this:
<PropBlk_InputLine headtext='Projectnaam *' value={fields.ProjectNaam} inputfield='inp_projectnaam' onChange={this.onInput} />
<PropBlk_InputDate headtext='Opdrachtdatum *' value={fields.DatumLabOpdracht} inputfield='inp_opdrachtdatum' onChange={this.onInput} />
This approach eliminates the structure with the ternaries, hence saves lines of code, and is more comprehensible.
Upvotes: 0
Reputation: 28654
There is no need to nest ternary operators like you have, you can do:
class PropertyBlock extends React.Component {
render() {
const { headtext, blockType, selectedId, selectOptions, onChange, extratext } = this.props;
let element;
switch(blockType){
case "dropdown" :
element = <PropBlk_Dropdown selectOptions={selectOptions} selectedId={selectedId} onChange={onChange} />;
break;
// go on here ...
}
return (
<div className='propblk'>
<div className='headline'>{headtext}</div>
{element}
</div>
)
}
}
Upvotes: 1