Last active
December 2, 2016 11:33
-
-
Save aliaksandr-master/c93821defee6bd0f377b66dfa2d924a7 to your computer and use it in GitHub Desktop.
ConnectUI
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'; | |
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