Skip to content

Instantly share code, notes, and snippets.

@hkjpotato
Last active July 12, 2017 15:23
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 hkjpotato/d9b9de0476255d638007b5887f23f194 to your computer and use it in GitHub Desktop.
Save hkjpotato/d9b9de0476255d638007b5887f23f194 to your computer and use it in GitHub Desktop.
//1. it is stateful because it knows whether the React Component should update
function makeSelectorStateful(selector, store) {
// wrap the selector in an object that tracks its results between runs.
const statefulSelector = {
run: function (props) {
const nextProps = selector(store.getState(), props);
//but it set shouldComponentUpdate to true if it is a different from previous one
if (nextProps !== statefulSelector.props) {
//update info for React
statefulSelector.shouldComponentUpdate = true;
statefulSelector.props = nextProps;
}
}
}
return statefulSelector
}
function connectHOC(mapStateToProps, mapDispatchToProps) {
return function wrapWithConnect(WrappedComponent) {
class Connect extends React.Component {
constructor(props, context) {
super(props, context)
this.store = context.store //access store from context
this.initSelector()
//...subscrition
}
initSelector() {
const selector = selectorFactory(this.store.dispatch, mapStateToProps, mapDispatchToProps)
this.selector = makeSelectorStateful(selector, this.store)
//init the mergedProp for initial render
this.selector.run(this.props)
}
//data source 1: store state change
onStateChange() {
this.selector.run(this.props)
if (!this.selector.shouldComponentUpdate) {
//if it does not get re-render, we still need to notify the nested subscription
this.subscription.notifyNestedSubs()
} else {
this.componentDidUpdate = this.notifyNestedSubsOnComponentDidUpdate
this.setState({})
}
}
notifyNestedSubsOnComponentDidUpdate() {
this.componentDidUpdate = undefined; //unimplement it to avoid notification due to normal update(e.g. parent's re-render)
this.subscription.notifyNestedSubs();
}
//data source 2: ownProps change
componentWillReceiveProps(nextProps) {
//run the stateful selector to update mergedProps
this.selector.run(nextProps)
}
shouldComponentUpdate() {
//rely on the stateful selector, prevent unecessary re-render
return this.selector.shouldComponentUpdate
}
render() {
const selector = this.selector
selector.shouldComponentUpdate = false //reset the flag of the selector
return React.createElement(WrappedComponent, selector.props) //get the mergedProps from the selector
}
}
//....
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment