Skip to content

Instantly share code, notes, and snippets.

@joecritch
Last active December 1, 2016 05:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joecritch/8755865 to your computer and use it in GitHub Desktop.
Save joecritch/8755865 to your computer and use it in GitHub Desktop.
React mixin to add named outlets to a component, ready for transclusion
var WithOutlets = {
componentWillMount: function() {
this.setOutlets(this.props);
},
componentWillUpdate: function(nextProps) {
if(!nextProps || this.props.children !== nextProps.children) {
this.setOutlets(nextProps);
}
},
setOutlets: function(props) {
props.outlets = {};
// Get the outlets from the children with a outlet="" property
props.children.forEach(function(child) {
if(!child) return false; // Sometimes children aren't children at all, during conditional statements (they're 'false')
if(child.props.outlet) {
props.outlets[child.props.outlet] = child;
}
});
// Remove any with outlet properties and add them to a separate props.
props.children = props.children.filter(function(child, i) {
return child && !child.props.outlet;
});
}
};
/** @jsx React.DOM */
var MyLayout = React.createClass({
mixins: [WithOutlets],
render: function() {
return (
<div className="my-layout">
{this.props.outlets.header &&
<div className="my-layout__header">
{this.props.outlets.header}
</div>
}
<div className="my-layout__body">
{this.props.children}
</div>
{this.props.outlets.footer &&
<div className="my-layout__footer">
{this.props.outlets.footer}
</div>
}
</div>
);
}
});
var MyApp = React.createClass({
render: function() {
return (
<MyLayout>
<h1 outlet="header">Title for the header</h1>
<p>Content for the body of the component.</p>
<div outlet="footer">
<a href="#">Footer</a> |
<a href="#">Links</a>
</div>
</MyLayout>
);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment