Skip to content

Instantly share code, notes, and snippets.

@w3aran
Last active October 9, 2016 13:19
Show Gist options
  • Save w3aran/a3224856ef63b71e6cabaf560a5d91f0 to your computer and use it in GitHub Desktop.
Save w3aran/a3224856ef63b71e6cabaf560a5d91f0 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'
// LOCAL REDUX STORE
// =================
// features/counter/store/actions.js
const SET_STORE_KEY = "SET_STORE_KEY";
const INCREMENT = "INCREMENT";
// features/counter/store/action-creator.js
const setStoreKey = (storeKeyName) => ({
type: SET_STORE_KEY, payload: { storeKeyName }
});
const increment = (storeKeyName) => ({
type: INCREMENT, meta: { storeKeyName }
});
// features/counter/store/reducer.js
const defaultReducerKeyName = "";
const defaultStoreKeyName = "default";
const defaultState = { [defaultStoreKeyName]: { value: 0 } };
const counter = (state = defaultState, action) => {
console.log("|------------------------------------------------------|");
console.log("state: ", JSON.stringify(state));
console.log("action: ", JSON.stringify(action));
console.log("|______________________________________________________|");
const strategy = {
[SET_STORE_KEY]: (state, action) => ({
...state,
[action.payload.storeKeyName]: defaultState[defaultStoreKeyName]
}),
[INCREMENT]: (state, action) => ({
...state,
[action.meta.storeKeyName]: {
value: state[action.meta.storeKeyName].value + 1
}
}),
default: (state, action) => state
};
return (strategy[action.type] || strategy.default)(state, action);
};
// features/counter/store/index.js
const counterStore = createStore(counter);
// feature/counter/store/connect/index.js
const connectFeatureStore = ({
store, reducerKeyName = defaultReducerKeyName, storeKeyName = defaultStoreKeyName, setStoreKey, mapStateToProps, mapDispatchToProps
}) => (WrappedComponent) => {
const displayName = `connectFeatureStore(${getDisplayName(WrappedComponent)})`;
if (setStoreKey) store.dispatch(setStoreKey(storeKeyName));
class FeatureStoreContainer extends Component {
constructor(props) {
super(props);
this.state = this.stateShape();
this.unsubscribe = store.subscribe(this.handleStoreChanges.bind(this));
}
stateShape() {
const state = reducerKeyName ? store.getState()[reducerKeyName] : store.getState();
return mapStateToProps(state, storeKeyName, this.props);
}
componentWillUnmount() {
this.unsubscribe()
}
handleStoreChanges() {
this.setState(this.stateShape())
}
render() {
return (
<WrappedComponent
{...this.props}
{...this.state}
{...mapDispatchToProps(store.dispatch, storeKeyName, this.props)}
/>
);
}
}
FeatureStoreContainer.displayName = displayName;
return FeatureStoreContainer;
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
const mapStateToProps = (state, storeKeyName, props) => ({
value: state[storeKeyName].value
});
const mapDispatchToProps = (dispatch, storeKeyName, props) => ({
onAdd: () => dispatch(increment(storeKeyName))
});
// PURE PRESENTATIONAL COMPONENTS
// ============================
// features/counter/components/counter-a.js
const CounterAView = ({ value, onAdd }) => (
<div>
<h1>{value}</h1>
<button onClick={onAdd}>+</button>
</div>
);
const CounterA = connectFeatureStore({
store: counterStore, storeKeyName: "counterA", setStoreKey, mapStateToProps, mapDispatchToProps
})(CounterAView);
// 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 = connectFeatureStore({
store: counterStore, storeKeyName: "counterB", setStoreKey, mapStateToProps, mapDispatchToProps
})(CounterBView);
const App = () => (
<div>
<CounterA />
<hr />
<CounterB />
</div>
);
ReactDOM.render(
<App />,
document.getElementById("App")
);
{
"name": "feature-redux-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 _extends4 = require('babel-runtime/helpers/extends');
var _extends5 = _interopRequireDefault(_extends4);
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
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 }; }
// LOCAL REDUX STORE
// =================
// features/counter/store/actions.js
var SET_STORE_KEY = "SET_STORE_KEY";
var INCREMENT = "INCREMENT";
// features/counter/store/action-creator.js
var setStoreKey = function setStoreKey(storeKeyName) {
return {
type: SET_STORE_KEY, payload: { storeKeyName: storeKeyName }
};
};
var increment = function increment(storeKeyName) {
return {
type: INCREMENT, meta: { storeKeyName: storeKeyName }
};
};
// features/counter/store/reducer.js
var defaultReducerKeyName = "";
var defaultStoreKeyName = "default";
var defaultState = (0, _defineProperty3.default)({}, defaultStoreKeyName, { value: 0 });
var counter = function counter() {
var _strategy;
var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0];
var action = arguments[1];
console.log("|------------------------------------------------------|");
console.log("state: ", (0, _stringify2.default)(state));
console.log("action: ", (0, _stringify2.default)(action));
console.log("|______________________________________________________|");
var strategy = (_strategy = {}, (0, _defineProperty3.default)(_strategy, SET_STORE_KEY, function (state, action) {
return (0, _extends5.default)({}, state, (0, _defineProperty3.default)({}, action.payload.storeKeyName, defaultState[defaultStoreKeyName]));
}), (0, _defineProperty3.default)(_strategy, INCREMENT, function (state, action) {
return (0, _extends5.default)({}, state, (0, _defineProperty3.default)({}, action.meta.storeKeyName, {
value: state[action.meta.storeKeyName].value + 1
}));
}), (0, _defineProperty3.default)(_strategy, 'default', function _default(state, action) {
return state;
}), _strategy);
return (strategy[action.type] || strategy.default)(state, action);
};
// features/counter/store/index.js
var counterStore = (0, _redux.createStore)(counter);
// feature/counter/store/connect/index.js
var connectFeatureStore = function connectFeatureStore(_ref) {
var store = _ref.store;
var _ref$reducerKeyName = _ref.reducerKeyName;
var reducerKeyName = _ref$reducerKeyName === undefined ? defaultReducerKeyName : _ref$reducerKeyName;
var _ref$storeKeyName = _ref.storeKeyName;
var storeKeyName = _ref$storeKeyName === undefined ? defaultStoreKeyName : _ref$storeKeyName;
var setStoreKey = _ref.setStoreKey;
var mapStateToProps = _ref.mapStateToProps;
var mapDispatchToProps = _ref.mapDispatchToProps;
return function (WrappedComponent) {
var displayName = 'connectFeatureStore(' + getDisplayName(WrappedComponent) + ')';
if (setStoreKey) store.dispatch(setStoreKey(storeKeyName));
var FeatureStoreContainer = function (_Component) {
(0, _inherits3.default)(FeatureStoreContainer, _Component);
function FeatureStoreContainer(props) {
(0, _classCallCheck3.default)(this, FeatureStoreContainer);
var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(FeatureStoreContainer).call(this, props));
_this.state = _this.stateShape();
_this.unsubscribe = store.subscribe(_this.handleStoreChanges.bind(_this));
return _this;
}
(0, _createClass3.default)(FeatureStoreContainer, [{
key: 'stateShape',
value: function stateShape() {
var state = reducerKeyName ? store.getState()[reducerKeyName] : store.getState();
return mapStateToProps(state, storeKeyName, this.props);
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.unsubscribe();
}
}, {
key: 'handleStoreChanges',
value: function handleStoreChanges() {
this.setState(this.stateShape());
}
}, {
key: 'render',
value: function render() {
return _react2.default.createElement(WrappedComponent, (0, _extends5.default)({}, this.props, this.state, mapDispatchToProps(store.dispatch, storeKeyName, this.props)));
}
}]);
return FeatureStoreContainer;
}(_react.Component);
FeatureStoreContainer.displayName = displayName;
return FeatureStoreContainer;
};
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
var mapStateToProps = function mapStateToProps(state, storeKeyName, props) {
return {
value: state[storeKeyName].value
};
};
var mapDispatchToProps = function mapDispatchToProps(dispatch, storeKeyName, props) {
return {
onAdd: function onAdd() {
return dispatch(increment(storeKeyName));
}
};
};
// PURE PRESENTATIONAL COMPONENTS
// ============================
// features/counter/components/counter-a.js
var CounterAView = function CounterAView(_ref2) {
var value = _ref2.value;
var onAdd = _ref2.onAdd;
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(
'h1',
null,
value
),
_react2.default.createElement(
'button',
{ onClick: onAdd },
'+'
)
);
};
var CounterA = connectFeatureStore({
store: counterStore, storeKeyName: "counterA", setStoreKey: setStoreKey, mapStateToProps: mapStateToProps, mapDispatchToProps: mapDispatchToProps
})(CounterAView);
// 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(_ref3) {
var value = _ref3.value;
var onAdd = _ref3.onAdd;
return _react2.default.createElement(
'div',
{ style: CounterBViewStyle },
value,
' ',
_react2.default.createElement(
'button',
{ onClick: onAdd, style: CounterBViewButtonStyle },
'+'
)
);
};
var CounterB = connectFeatureStore({
store: counterStore, storeKeyName: "counterB", setStoreKey: setStoreKey, mapStateToProps: mapStateToProps, mapDispatchToProps: mapDispatchToProps
})(CounterBView);
var App = function App() {
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(CounterA, null),
_react2.default.createElement('hr', 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