made with esnextbin
Created
December 21, 2016 05:54
-
-
Save kentcdodds/3a401fad2f8a39f543dbf568378e296e to your computer and use it in GitHub Desktop.
esnextbin sketch
This file contains 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
<html> | |
<head> | |
<link rel="stylesheet" href="https://unpkg.com/milligram@1.2.4" /> | |
</head> | |
<body> | |
<div id="root"></div> | |
</body> | |
</html> |
This file contains 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
import React, {Component, PropTypes} from 'react' | |
import ReactDOM from 'react-dom' | |
class StateSetter extends Component { | |
constructor(props, ...rest) { | |
super(props, ...rest) | |
this.state = props.initialState || {} | |
} | |
render() { | |
return this.props.children(this.state, (...args) => this.setState(...args)) | |
} | |
} | |
function withContext(context) { | |
class StateSetterWithContext extends StateSetter { | |
getChildContext() { // eslint-disable-line | |
return context | |
} | |
} | |
StateSetterWithContext.childContextTypes = Object.keys(context).reduce((types, key) => { | |
types[key] = PropTypes.any | |
return types | |
}, {}) | |
return StateSetterWithContext | |
} | |
const context = { | |
color: 'black', | |
} | |
setInterval(() => { | |
context.color = context.color === 'black' ? 'gray' : 'black' | |
}, 1000) | |
const StateSetterWithColorContext = withContext(context) | |
function getThislessComponent(getModule, staticProperties) { | |
class Thisless extends React.Component { | |
constructor(...args) { | |
super(...args) | |
const result = getModule(this, ...args) | |
Object.assign(this, result) | |
} | |
} | |
Object.assign(Thisless, staticProperties) | |
return Thisless | |
} | |
const SmileyFace = getThislessComponent((instance, props) => { // access to props (and context) | |
let canChangeHappyState = false // legit private property, no extra wacky syntax. Just JavaScript function closures. | |
// just return React component object | |
return { | |
state: {happy: props.initialHappyState}, // basically like public class fields, except no special syntax | |
onButtonClick() { // no worries about binding this or using public class fields, because you're not using `this`! | |
if (canChangeHappyState) { | |
instance.setState({happy: !instance.state.happy}) | |
} | |
}, | |
componentDidMount() { // Real component lifecycle methods! They all work! | |
setTimeout(() => { | |
canChangeHappyState = true | |
}, 5000) | |
}, | |
render() { | |
// access to state, props, and context just like from `this` | |
// except it's from the `instance` | |
const {happy} = instance.state | |
const {clicks} = instance.props | |
const {color} = instance.context | |
return ( | |
<div> | |
<div style={{width: 350}}> | |
Cannot change happy state for the first 5 seconds due to a genuine | |
private <code>canChangeHappyState</code> variable, which | |
is: {JSON.stringify(canChangeHappyState)} | |
</div> | |
<button onClick={instance.onButtonClick}> | |
instance.state.happy: {happy ? ':-)' : ':-('} | |
</button> | |
<div>instance.props.clicks: {clicks}</div> | |
<div style={{color}}>instance.context.color: {color}</div> | |
</div> | |
) | |
}, | |
} | |
}, { // static properties go here :) | |
defaultProps: {initialHappyState: true}, | |
propTypes: {initialHappyState: React.PropTypes.bool}, | |
contextTypes: {color: React.PropTypes.string}, | |
}) | |
const root = ( | |
<StateSetterWithColorContext initialState={{clicks: 0}}> | |
{({clicks}, setState) => ( | |
<div style={{margin: 70}}> | |
<div style={{marginRight: 20}}> | |
<button onClick={() => setState({clicks: clicks + 1})}>click me</button> | |
<SmileyFace clicks={clicks} /> | |
<div style={{width: 400, marginTop: 50}}> | |
Just experimenting for fun. Please spare me the "what about perf?" and "I don't like this" and | |
"this isn't really better" or "yeah, duh!" yada yada. I'm just a programmer having some fun... But I | |
think it's neat! Creating components via the module pattern! Private members are easy and obvious. | |
State, props, and context all without using `this` or classes. Lifecycle methods work too. | |
All from 10 lines of code :) | |
</div> | |
</div> | |
</div> | |
)} | |
</StateSetterWithColorContext> | |
) | |
ReactDOM.render( | |
root, | |
document.getElementById('root') | |
) |
This file contains 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
{ | |
"name": "esnextbin-sketch", | |
"version": "0.0.0", | |
"dependencies": { | |
"react": "15.4.1", | |
"react-dom": "15.4.1", | |
"babel-runtime": "6.20.0" | |
} | |
} |
This file contains 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 _stringify = require('babel-runtime/core-js/json/stringify'); | |
var _stringify2 = _interopRequireDefault(_stringify); | |
var _extends2 = require('babel-runtime/helpers/extends'); | |
var _extends3 = _interopRequireDefault(_extends2); | |
var _keys = require('babel-runtime/core-js/object/keys'); | |
var _keys2 = _interopRequireDefault(_keys); | |
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); | |
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); | |
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); | |
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); | |
var _createClass2 = require('babel-runtime/helpers/createClass'); | |
var _createClass3 = _interopRequireDefault(_createClass2); | |
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); | |
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); | |
var _inherits2 = require('babel-runtime/helpers/inherits'); | |
var _inherits3 = _interopRequireDefault(_inherits2); | |
var _react = require('react'); | |
var _react2 = _interopRequireDefault(_react); | |
var _reactDom = require('react-dom'); | |
var _reactDom2 = _interopRequireDefault(_reactDom); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
var StateSetter = function (_Component) { | |
(0, _inherits3.default)(StateSetter, _Component); | |
function StateSetter(props) { | |
var _Object$getPrototypeO; | |
(0, _classCallCheck3.default)(this, StateSetter); | |
for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | |
rest[_key - 1] = arguments[_key]; | |
} | |
var _this = (0, _possibleConstructorReturn3.default)(this, (_Object$getPrototypeO = (0, _getPrototypeOf2.default)(StateSetter)).call.apply(_Object$getPrototypeO, [this, props].concat(rest))); | |
_this.state = props.initialState || {}; | |
return _this; | |
} | |
(0, _createClass3.default)(StateSetter, [{ | |
key: 'render', | |
value: function render() { | |
var _this2 = this; | |
return this.props.children(this.state, function () { | |
return _this2.setState.apply(_this2, arguments); | |
}); | |
} | |
}]); | |
return StateSetter; | |
}(_react.Component); | |
function withContext(context) { | |
var StateSetterWithContext = function (_StateSetter) { | |
(0, _inherits3.default)(StateSetterWithContext, _StateSetter); | |
function StateSetterWithContext() { | |
(0, _classCallCheck3.default)(this, StateSetterWithContext); | |
return (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(StateSetterWithContext).apply(this, arguments)); | |
} | |
(0, _createClass3.default)(StateSetterWithContext, [{ | |
key: 'getChildContext', | |
value: function getChildContext() { | |
// eslint-disable-line | |
return context; | |
} | |
}]); | |
return StateSetterWithContext; | |
}(StateSetter); | |
StateSetterWithContext.childContextTypes = (0, _keys2.default)(context).reduce(function (types, key) { | |
types[key] = _react.PropTypes.any; | |
return types; | |
}, {}); | |
return StateSetterWithContext; | |
} | |
var context = { | |
color: 'black' | |
}; | |
setInterval(function () { | |
context.color = context.color === 'black' ? 'gray' : 'black'; | |
}, 1000); | |
var StateSetterWithColorContext = withContext(context); | |
function getThislessComponent(getModule, staticProperties) { | |
var Thisless = function (_React$Component) { | |
(0, _inherits3.default)(Thisless, _React$Component); | |
function Thisless() { | |
var _Object$getPrototypeO2; | |
(0, _classCallCheck3.default)(this, Thisless); | |
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | |
args[_key2] = arguments[_key2]; | |
} | |
var _this4 = (0, _possibleConstructorReturn3.default)(this, (_Object$getPrototypeO2 = (0, _getPrototypeOf2.default)(Thisless)).call.apply(_Object$getPrototypeO2, [this].concat(args))); | |
var result = getModule.apply(undefined, [_this4].concat(args)); | |
(0, _extends3.default)(_this4, result); | |
return _this4; | |
} | |
return Thisless; | |
}(_react2.default.Component); | |
(0, _extends3.default)(Thisless, staticProperties); | |
return Thisless; | |
} | |
var SmileyFace = getThislessComponent(function (instance, props) { | |
// access to props (and context) | |
var canChangeHappyState = false; // legit private property, no extra wacky syntax. Just JavaScript function closures. | |
// just return React component object | |
return { | |
state: { happy: props.initialHappyState }, // basically like public class fields, except no special syntax | |
onButtonClick: function onButtonClick() { | |
// no worries about binding this or using public class fields, because you're not using `this`! | |
if (canChangeHappyState) { | |
instance.setState({ happy: !instance.state.happy }); | |
} | |
}, | |
componentDidMount: function componentDidMount() { | |
// Real component lifecycle methods! They all work! | |
setTimeout(function () { | |
canChangeHappyState = true; | |
}, 5000); | |
}, | |
render: function render() { | |
// access to state, props, and context just like from `this` | |
// except it's from the `instance` | |
var happy = instance.state.happy; | |
var clicks = instance.props.clicks; | |
var color = instance.context.color; | |
return _react2.default.createElement( | |
'div', | |
null, | |
_react2.default.createElement( | |
'div', | |
{ style: { width: 350 } }, | |
'Cannot change happy state for the first 5 seconds due to a genuine private ', | |
_react2.default.createElement( | |
'code', | |
null, | |
'canChangeHappyState' | |
), | |
' variable, which is: ', | |
(0, _stringify2.default)(canChangeHappyState) | |
), | |
_react2.default.createElement( | |
'button', | |
{ onClick: instance.onButtonClick }, | |
'instance.state.happy: ', | |
happy ? ':-)' : ':-(' | |
), | |
_react2.default.createElement( | |
'div', | |
null, | |
'instance.props.clicks: ', | |
clicks | |
), | |
_react2.default.createElement( | |
'div', | |
{ style: { color: color } }, | |
'instance.context.color: ', | |
color | |
) | |
); | |
} | |
}; | |
}, { // static properties go here :) | |
defaultProps: { initialHappyState: true }, | |
propTypes: { initialHappyState: _react2.default.PropTypes.bool }, | |
contextTypes: { color: _react2.default.PropTypes.string } | |
}); | |
var root = _react2.default.createElement( | |
StateSetterWithColorContext, | |
{ initialState: { clicks: 0 } }, | |
function (_ref, setState) { | |
var clicks = _ref.clicks; | |
return _react2.default.createElement( | |
'div', | |
{ style: { margin: 70 } }, | |
_react2.default.createElement( | |
'div', | |
{ style: { marginRight: 20 } }, | |
_react2.default.createElement( | |
'button', | |
{ onClick: function onClick() { | |
return setState({ clicks: clicks + 1 }); | |
} }, | |
'click me' | |
), | |
_react2.default.createElement(SmileyFace, { clicks: clicks }), | |
_react2.default.createElement( | |
'div', | |
{ style: { width: 400, marginTop: 50 } }, | |
'Just experimenting for fun. Please spare me the "what about perf?" and "I don\'t like this" and "this isn\'t really better" or "yeah, duh!" yada yada. I\'m just a programmer having some fun... But I think it\'s neat! Creating components via the module pattern! Private members are easy and obvious. State, props, and context all without using `this` or classes. Lifecycle methods work too. All from 10 lines of code :)' | |
) | |
) | |
); | |
} | |
); | |
_reactDom2.default.render(root, document.getElementById('root')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment