Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27306

JSX element literals with partially supplied properties

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.)

update

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

Answers (1)

Sean Vieira
Sean Vieira

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

Related Questions