Last active
August 29, 2015 14:07
-
-
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/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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')) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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 <div> | |
<h1>Base Heading</h1> | |
<Block id="content"> | |
<h2>Base Content</h2> | |
</Block> | |
</div> | |
} | |
}) | |
var Abstract = React.createClass({ | |
mixins: [BlocksMixin], | |
render: function() { | |
return <Base> | |
<Block id="content"> | |
<Super/> | |
<h2>Abstract Content</h2> | |
</Block> | |
</Base> | |
} | |
}) | |
var Concrete = React.createClass({ | |
render: function() { | |
return <Abstract> | |
<Block id="content"> | |
<Super/> | |
<h2>Concrete Content</h2> | |
</Block> | |
</Abstract> | |
} | |
}) | |
React.render(<Concrete/>, 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