Skip to content

Instantly share code, notes, and snippets.

@insin
Last active August 29, 2015 14:07
Show Gist options
  • Save insin/bcca5b64c6bcf95ad535 to your computer and use it in GitHub Desktop.
Save insin/bcca5b64c6bcf95ad535 to your computer and use it in GitHub Desktop.
A failed attempt to implement block inheritance using React contexts (Live version with console logs: http://bl.ocks.org/insin/raw/bcca5b64c6bcf95ad535/)
'use strict';
var BlocksMixin = {
contextTypes: {
blocks: React.PropTypes.object
},
childContextTypes: {
blocks: React.PropTypes.object.isRequired
},
// Create or add to FIFO queues of <Block/>s, keyed by their id
getChildContext: function () {
console.log('Creating ', this.props.log, ' BlocksMixin childContext')
var blocks = this.context.blocks || {}
React.Children.forEach(this.props.children, function(block) {
var id = block.props.id
if (Array.isArray(blocks[id])) {
blocks[id].unshift(block)
}
else {
blocks[id] = [block]
}
})
return {
blocks: blocks
}
}
}
var Block = React.createClass({
propTypes: {
id: React.PropTypes.string.isRequired
},
contextTypes: {
blocks: React.PropTypes.object
},
childContextTypes: {
blockId: React.PropTypes.string.isRequired
},
getChildContext: function () {
var childContext = { blockId: this.props.id }
console.log('Creating ', this.props.log, ' Block childContext', childContext)
return childContext
},
// Pop a <Block/> off the appropraite queue and render its children
render: function() {
console.log('Rendering', this.props.log, ' Block')
return <div>{this.context.blocks[this.props.id].pop().props.children}</div>
}
})
var Super = React.createClass({
contextTypes: {
blocks: React.PropTypes.object.isRequired,
blockId: React.PropTypes.string.isRequired
},
// A <Super/> should pop the next <Block/> off the appropraite queue and
// render it - why are blocks and blockId undefined in this.context?
render: function() {
console.log('Rendering', this.props.log, ' Super', console.log(this.context))
return <div>{
this.context.blockId && this.context.blocks[this.props.id].pop().props.children
}</div>
}
})
var Base = React.createClass({
mixins: [BlocksMixin],
render: function() {
console.log('Rendering Base')
return <div>
<h1>Base Heading</h1>
<Block id="content" log="base-content">
<h2>Base Content</h2>
</Block>
</div>
}
})
var Abstract = React.createClass({
mixins: [BlocksMixin],
render: function() {
console.log('Rendering Abstract')
return <Base log="base">
<Block id="content" log="abstract-content">
<Super log="abstract-super"/>
<h2>Abstract Content</h2>
</Block>
</Base>
}
})
var Concrete = React.createClass({
render: function() {
console.log('Rendering Concrete')
return <Abstract log="abstract">
<Block id="content" log="concrete-content">
<Super log="concrete-super"/>
<h2>Concrete Content</h2>
</Block>
</Abstract>
}
})
React.render(<Concrete log="concrete"/>, document.getElementById('app'))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React Blocks</title>
<script src="http://fb.me/react-with-addons-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
<style>
.example {
border: 2px solid #000;
border-radius: 1em;
padding: 0 1em;
}
</style>
</head>
<body>
<h1>Components</h1>
<pre>var Base = React.createClass({
mixins: [BlocksMixin],
render: function() {
return &lt;div&gt;
&lt;h1&gt;Base Heading&lt;/h1&gt;
&lt;Block id="content"&gt;
&lt;h2&gt;Base Content&lt;/h2&gt;
&lt;/Block&gt;
&lt;/div&gt;
}
})
var Abstract = React.createClass({
mixins: [BlocksMixin],
render: function() {
return &lt;Base&gt;
&lt;Block id="content"&gt;
&lt;Super/&gt;
&lt;h2&gt;Abstract Content&lt;/h2&gt;
&lt;/Block&gt;
&lt;/Base&gt;
}
})
var Concrete = React.createClass({
render: function() {
return &lt;Abstract&gt;
&lt;Block id="content"&gt;
&lt;Super/&gt;
&lt;h2&gt;Concrete Content&lt;/h2&gt;
&lt;/Block&gt;
&lt;/Abstract&gt;
}
})
React.render(&lt;Concrete/&gt;, document.getElementById('app'))</pre>
<h1>Expected</h1>
<div class="example">
<h1>Base Heading</h1>
<h2>Base Content</h2>
<h2>Abstract Content</h2>
<h2>Concrete Content</h2>
</div>
<h1>Actual</h1>
<div class="example" id="app"></div>
<script type="text/jsx" src="app.jsx"></script>
<a href="https://gist.github.com/insin/bcca5b64c6bcf95ad535"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment