Skip to content

Commit

Permalink
Data: Optimize withSelect shouldComponentUpdate (#6457)
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth authored Apr 30, 2018
1 parent f037e90 commit 7b62a34
Showing 1 changed file with 62 additions and 51 deletions.
113 changes: 62 additions & 51 deletions data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,69 +278,80 @@ export function dispatch( reducerKey ) {
*
* @return {Component} Enhanced component with merged state data props.
*/
export const withSelect = ( mapStateToProps ) => createHigherOrderComponent(
compose( [
pure,
( WrappedComponent ) => {
return class ComponentWithSelect extends Component {
constructor() {
super( ...arguments );
export const withSelect = ( mapStateToProps ) => createHigherOrderComponent( ( WrappedComponent ) => {
return class ComponentWithSelect extends Component {
constructor() {
super( ...arguments );

this.runSelection = this.runSelection.bind( this );

/**
* Boolean tracking known render conditions (own props or merged
* props update) for `shouldComponentUpdate`.
*
* @type {boolean}
*/
this.shouldComponentUpdate = false;

this.state = {};
}

this.runSelection = this.runSelection.bind( this );
shouldComponentUpdate() {
return this.shouldComponentUpdate;
}

this.state = {};
}
componentWillMount() {
this.subscribe();

componentWillMount() {
this.subscribe();
// Populate initial state.
this.runSelection();
}

// Populate initial state.
this.runSelection();
}
componentWillReceiveProps( nextProps ) {
if ( ! isShallowEqual( nextProps, this.props ) ) {
this.runSelection( nextProps );
this.shouldComponentUpdate = true;
}
}

componentWillReceiveProps( nextProps ) {
if ( ! isShallowEqual( nextProps, this.props ) ) {
this.runSelection( nextProps );
}
}
componentWillUnmount() {
this.unsubscribe();

componentWillUnmount() {
this.unsubscribe();
// While above unsubscribe avoids future listener calls, callbacks
// are snapshotted before being invoked, so if unmounting occurs
// during a previous callback, we need to explicitly track and
// avoid the `runSelection` that is scheduled to occur.
this.isUnmounting = true;
}

// While above unsubscribe avoids future listener calls, callbacks
// are snapshotted before being invoked, so if unmounting occurs
// during a previous callback, we need to explicitly track and
// avoid the `runSelection` that is scheduled to occur.
this.isUnmounting = true;
}
subscribe() {
this.unsubscribe = subscribe( this.runSelection );
}

subscribe() {
this.unsubscribe = subscribe( this.runSelection );
}
runSelection( props = this.props ) {
if ( this.isUnmounting ) {
return;
}

runSelection( props = this.props ) {
if ( this.isUnmounting ) {
return;
}
const { mergeProps } = this.state;
const nextMergeProps = mapStateToProps( select, props ) || {};

const { mergeProps } = this.state;
const nextMergeProps = mapStateToProps( select, props ) || {};
if ( ! isShallowEqual( nextMergeProps, mergeProps ) ) {
this.setState( {
mergeProps: nextMergeProps,
} );

if ( ! isShallowEqual( nextMergeProps, mergeProps ) ) {
this.setState( {
mergeProps: nextMergeProps,
} );
}
}
this.shouldComponentUpdate = true;
}
}

render() {
return <WrappedComponent { ...this.props } { ...this.state.mergeProps } />;
}
};
},
] ),
'withSelect'
);
render() {
this.shouldComponentUpdate = false;

return <WrappedComponent { ...this.props } { ...this.state.mergeProps } />;
}
};
}, 'withSelect' );

/**
* Higher-order component used to add dispatch props using registered action
Expand Down

0 comments on commit 7b62a34

Please sign in to comment.