Skip to content

Instantly share code, notes, and snippets.

@aliaksandr-master
Last active December 2, 2016 11:33
Show Gist options
  • Save aliaksandr-master/c93821defee6bd0f377b66dfa2d924a7 to your computer and use it in GitHub Desktop.
Save aliaksandr-master/c93821defee6bd0f377b66dfa2d924a7 to your computer and use it in GitHub Desktop.
ConnectUI
'use strict';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import compose from 'recompose/compose';
import reduce from 'lodash/reduce';
import identity from 'lodash/identity';
import kebabCase from 'lodash/kebabCase';
const MOUNT = 'ui.MOUNT';
const UNMOUNT = 'ui.UNMOUNT';
const dynamicReducers = {};
const uiReducer = (state = {}, action) => {
if (!action.type.startsWith('ui.')) {
return state;
}
return reduce(dynamicReducers, (newState, reducer, key) => ({
...newState,
[key]: reducer(newState[key], action)
}), state);
};
export const connectUi = ({ reducer = identity }, mapStateToProps, mapDispatchToProps) =>
compose(
(Target) => {
const baseId = Target.displayName || Target.name;
return class extends Component {
static contextTypes = {
store: PropTypes.shape({ dispatch: PropTypes.func.isRequired })
};
static propTypes = {
key: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
uiID: PropTypes.string.isRequired
};
static displayName = `ConnectUi(${Target.displayName || Target.name})`;
componentWillMount () {
if (!this.props.uiID) {
throw new Error('uiID is empty!');
}
this.uiID = `${baseId}::${this.props.uiID}[${this.key || 0}]`;
if (dynamicReducers.hasOwnProperty(this.uiID)) {
throw new Error(`duplicate uiID "${this.uiID}"`);
}
dynamicReducers[this.uiID] = reducer;
this.context.store.dispatch({
type: MOUNT,
meta: { uiID: this.uiID },
payload: {}
});
}
componentWillUnmount () {
delete dynamicReducers[this.uiID];
this.context.store.dispatch({
type: UNMOUNT,
meta: { uiID: this.uiID },
payload: {}
});
}
render () {
return (<Target {...this.props} uiID={this.uiID} />);
}
};
},
connect(
mapStateToProps ? (state, ownProps) => mapStateToProps(state.ui[ownProps.uiID], state, ownProps) : null,
mapDispatchToProps
)
);
export { uiReducer as reducer };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment