Skip to content

Instantly share code, notes, and snippets.

@w3aran
Last active October 7, 2016 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save w3aran/26595433156793f6106d8dcc285c5403 to your computer and use it in GitHub Desktop.
Save w3aran/26595433156793f6106d8dcc285c5403 to your computer and use it in GitHub Desktop.
esnextbin sketch
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ESNextbin Sketch</title>
<!-- put additional styles and scripts here -->
</head>
<body>
<!-- put markup and other contents here -->
<div id="App"></div>
</body>
</html>
import { createStore } from 'redux'
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
// SKIP to LINE #81 if you don't want to care about Application Logic and State management
// LOCAL REDUX STORE FOR COUNTER FEATURE MODULE
// ============================================
// features/counter/store/actions.js
const INCREMENT = "INCREMENT";
// features/counter/store/action-creator.js
const increment = (storeKeyName) => ({
type: INCREMENT, meta: { storeKeyName }
});
// features/counter/store/reducer.js
const defaultState = { default: { value: 0 } };
const counter = (state = defaultState, action) => {
if (action.type === INCREMENT) {
return {
...state,
[action.meta.storeKeyName]: {
value: ((state[action.meta.storeKeyName] || {}).value || 0) + 1 // Need to cleanup here
}
};
}
return state
};
// features/counter/store/index.js
const counterStore = createStore(counter);
// feature/counter/store/connect/index.js
const connectCounterStore = (WrappedComponent, storeKeyName = "default") => {
const displayName = `connectCounterStore(${getDisplayName(WrappedComponent)})`;
class CounterContainer extends Component {
constructor(props) {
super(props);
this.state = this.stateShape(); // If you don't want to use React's state, you could use this.forceUpdate()
this.unsubscribe = counterStore.subscribe(this.handleStoreChanges.bind(this));
}
stateShape() {
return counterStore.getState()[storeKeyName] || counterStore.getState().default;
}
componentWillUnmount() {
this.unsubscribe()
}
handleStoreChanges() {
this.setState(this.stateShape())
}
handleOnAdd() {
counterStore.dispatch(increment(storeKeyName))
}
render() {
return (
<WrappedComponent
{...this.state}
onAdd={this.handleOnAdd}
/>
);
}
}
CounterContainer.displayName = displayName;
return CounterContainer;
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
// PURE PRESENTATIONAL COMPONENTS
// ============================
// features/counter/components/counter-a.js
const CounterAView = ({ value, onAdd }) => (
<div>
<h1>{value}</h1>
<button onClick={onAdd}>+</button>
</div>
);
const CounterA = connectCounterStore(CounterAView, "counterA");
// features/counter/components/counter-b.js
const CounterBViewStyle = { padding: "2em", border: "1px solid brown", width: "50%", color: "brown", backgroundColor: "yellow" };
const CounterBViewButtonStyle = { width: "25%", backgroundColor: "brown", display: "block", padding: "1em" };
const CounterBView = ({ value, onAdd }) => (
<div style={CounterBViewStyle}>
{value} <button onClick={onAdd} style={CounterBViewButtonStyle}>+</button>
</div>
);
const CounterB = connectCounterStore(CounterBView, "counterB");
const App = () => (
<div>
<CounterA />
<CounterB />
</div>
);
ReactDOM.render(
<App />,
document.getElementById("App")
);
{
"name": "redux-counter-store",
"version": "0.0.1",
"dependencies": {
"redux": "3.6.0",
"react": "15.3.2",
"react-dom": "15.3.2",
"babel-runtime": "6.11.6"
}
}
'use strict';
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 _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends3 = require('babel-runtime/helpers/extends');
var _extends4 = _interopRequireDefault(_extends3);
var _redux = require('redux');
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 }; }
// SKIP to LINE #81 if you don't want to care about Application Logic and State management
// LOCAL REDUX STORE FOR COUNTER FEATURE MODULE
// ============================================
// features/counter/store/actions.js
var INCREMENT = "INCREMENT";
// features/counter/store/action-creator.js
var increment = function increment(storeKeyName) {
return {
type: INCREMENT, meta: { storeKeyName: storeKeyName }
};
};
// features/counter/store/reducer.js
var defaultState = { default: { value: 0 } };
var counter = function counter() {
var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0];
var action = arguments[1];
if (action.type === INCREMENT) {
return (0, _extends4.default)({}, state, (0, _defineProperty3.default)({}, action.meta.storeKeyName, {
value: ((state[action.meta.storeKeyName] || {}).value || 0) + 1 // Need to cleanup here
}));
}
return state;
};
// features/counter/store/index.js
var counterStore = (0, _redux.createStore)(counter);
// feature/counter/store/connect/index.js
var connectCounterStore = function connectCounterStore(WrappedComponent) {
var storeKeyName = arguments.length <= 1 || arguments[1] === undefined ? "default" : arguments[1];
var displayName = 'connectCounterStore(' + getDisplayName(WrappedComponent) + ')';
var CounterContainer = function (_Component) {
(0, _inherits3.default)(CounterContainer, _Component);
function CounterContainer(props) {
(0, _classCallCheck3.default)(this, CounterContainer);
var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(CounterContainer).call(this, props));
_this.state = _this.stateShape(); // If you don't want to use React's state, you could use this.forceUpdate()
_this.unsubscribe = counterStore.subscribe(_this.handleStoreChanges.bind(_this));
return _this;
}
(0, _createClass3.default)(CounterContainer, [{
key: 'stateShape',
value: function stateShape() {
return counterStore.getState()[storeKeyName] || counterStore.getState().default;
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.unsubscribe();
}
}, {
key: 'handleStoreChanges',
value: function handleStoreChanges() {
this.setState(this.stateShape());
}
}, {
key: 'handleOnAdd',
value: function handleOnAdd() {
counterStore.dispatch(increment(storeKeyName));
}
}, {
key: 'render',
value: function render() {
return _react2.default.createElement(WrappedComponent, (0, _extends4.default)({}, this.state, {
onAdd: this.handleOnAdd
}));
}
}]);
return CounterContainer;
}(_react.Component);
CounterContainer.displayName = displayName;
return CounterContainer;
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
// PURE PRESENTATIONAL COMPONENTS
// ============================
// features/counter/components/counter-a.js
var CounterAView = function CounterAView(_ref) {
var value = _ref.value;
var onAdd = _ref.onAdd;
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(
'h1',
null,
value
),
_react2.default.createElement(
'button',
{ onClick: onAdd },
'+'
)
);
};
var CounterA = connectCounterStore(CounterAView, "counterA");
// features/counter/components/counter-b.js
var CounterBViewStyle = { padding: "2em", border: "1px solid brown", width: "50%", color: "brown", backgroundColor: "yellow" };
var CounterBViewButtonStyle = { width: "25%", backgroundColor: "brown", display: "block", padding: "1em" };
var CounterBView = function CounterBView(_ref2) {
var value = _ref2.value;
var onAdd = _ref2.onAdd;
return _react2.default.createElement(
'div',
{ style: CounterBViewStyle },
value,
' ',
_react2.default.createElement(
'button',
{ onClick: onAdd, style: CounterBViewButtonStyle },
'+'
)
);
};
var CounterB = connectCounterStore(CounterBView, "counterB");
var App = function App() {
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(CounterA, null),
_react2.default.createElement(CounterB, null)
);
};
_reactDom2.default.render(_react2.default.createElement(App, null), document.getElementById("App"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment