Reputation: 27306
Using React.cloneElement
one can provide additional properties to partially-filled (for lack of a better word) elements. A contrived example would be:
function createPopulatedElement(el, v) {
return React.cloneElement(el, {value: v});
}
const ImportantContent = React.createClass({
render: function() {
return (
<strong> {this.props.value} </strong>
);
}
});
let populatedElement = createPopulatedElement(<ImportantContent/>, 'foo');
ReactDOM.render(populatedElement , $('#app2')[0]);
Now given that <ImportantContent/>
in the code above evaluates (?) to:
<strong>{this.props.value}</strong>
... I would like to be able to just do:
let populatedElement= createPopulatedElement(
(<span>{this.props.value} </span>),
'foo');
... without having to declare a wrapper React class (ImportantContent
in my case above). However the above code fails with:
Uncaught TypeError: Cannot read property 'value' of undefined
... which sort of makes sense. Is there a way to supply a partially populated (for lack of a better word) element to some function or ReactJS component (that will then add additional properties) as a JSX element literal without having to create a class?
(The above code is a SSCCE and I know that the separate createPopulatedElement
function doesn't make sense as I can directly pass value={'foo'}
when I instantiate the ImportantContent
component.)
ctrlplusb suggest using a stateless functional component. This is indeed slightly better than a class:
let F = (props)=>(<span>{props.value} </span>);
let populatedElement= createPopulatedElement(
<F/>
, 'foo');
ReactDOM.render(populatedElement, $('#app3')[0]);
... but still, a new type (F
) is introduced. Directly using an anonymous arrow function to make it even more compact and to avoid introducing a separate type fails parsing:
let populatedElement= createPopulatedElement(
<(props)=>(
<span>{props.value} </span>
)
/>
, 'foo');
Upvotes: 0
Views: 207
Reputation: 160063
You're almost there - when you create a stateless component and use it in one go you'll need to wrap it by hand in React.createElement
rather than using JSX:
let populatedElement= createPopulatedElement(
React.createElement(props => <span>{props.value}</span>),
'foo'
);
Upvotes: 2