Last active
September 17, 2015 16:34
-
-
Save qwtel/2b40d1a69932405d28aa to your computer and use it in GitHub Desktop.
Enhanced version of redux' connect, that puts all action creators into the child context of the component.
This file contains hidden or 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 {PropTypes} from 'react'; | |
import {connect} from 'react-redux'; | |
/** | |
* Enhanced version of redux' connect, that puts all action creators | |
* into the child context of the component. | |
* | |
* @param mapStateToProps {Function} | |
* @param mapDispatchToProps {Function} Must be free of side effects! | |
* @returns {Function} | |
*/ | |
export default function connectContext(mapStateToProps, mapDispatchToProps) { | |
const childContextTypes = getChildContextTypes(mapDispatchToProps); | |
const wrappedMapDispatchToProps = wrapDispatchToProps(mapDispatchToProps); | |
return component => { | |
overwriteChildContextTypes(component, childContextTypes); | |
overwriteGetChildContext(component); | |
return connect(mapStateToProps, wrappedMapDispatchToProps)(component); | |
}; | |
} | |
function getChildContextTypes(mapDispatchToProps) { | |
const childContextTypes = {}; | |
// Just interested in the keys. | |
// Hopefully your `mapDispatchToProps` implementation doesn't have side effects... | |
Object.keys(mapDispatchToProps(() => {})) | |
.forEach(key => { | |
// TODO: allow objectOf(func) | |
childContextTypes[key] = PropTypes.func; | |
}); | |
return childContextTypes; | |
} | |
function wrapDispatchToProps(mapDispatchToProps) { | |
return dispatch => { | |
const actionCreators = mapDispatchToProps(dispatch); | |
return { | |
actionCreators, | |
...actionCreators, // also include them in props, like a normal `connect` would do | |
}; | |
} | |
} | |
function overwriteChildContextTypes(component, childContextTypes) { | |
Object.assign(component.childContextTypes, childContextTypes); | |
} | |
function overwriteGetChildContext(component) { | |
const originalGetChildContext = component.prototype.getChildContext; | |
// using `function` so that `this` points to the actual instance of the component. | |
component.prototype.getChildContext = function () { | |
// get the original child context and assign all the `actionCreators` we "saved" in `props` on to it. | |
return Object.assign(originalGetChildContext.call(this), this.props.actionCreators); | |
}; | |
} | |
This file contains hidden or 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 {bindActionCreators} from 'redux'; | |
import connectContext from './connectContext'; | |
function click() { | |
return { | |
type: 'CLICK', | |
} | |
} | |
function mapStateToProps(state) { | |
return state; | |
} | |
function mapDispatchToProps(dispatch) { | |
return bindActionCreators({click}, dispatch); | |
} | |
@connectContext(mapStateToProps, mapDispatchToProps) | |
class Parent extends Component { | |
render() { | |
return <Child />; | |
} | |
} | |
class Child extends Component { | |
contextTypes: { | |
click: PropTypes.func, | |
} | |
render() { | |
<button onClick={this.context.click}/> | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment