Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit 7eae80e

Browse files
authored
Merge pull request #755 from danielericlee/perf-improvements
Perf improvements
2 parents 7581ae6 + 97182c4 commit 7eae80e

File tree

2 files changed

+201
-119
lines changed

2 files changed

+201
-119
lines changed

src/components/control-component.js

Lines changed: 194 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -651,128 +651,205 @@ function createControlClass(s = defaultStrategy) {
651651
};
652652
}
653653

654-
const ConnectedControl = resolveModel(connect(mapStateToProps)(Control));
654+
const ConnectedControl = resolveModel(connect(mapStateToProps, null, null, {
655+
areOwnPropsEqual(ownProps, nextOwnProps) {
656+
return shallowEqual(ownProps, nextOwnProps, {
657+
omitKeys: ['mapProps'],
658+
});
659+
},
660+
areStatePropsEqual(stateProps, nextStateProps) {
661+
return shallowEqual(stateProps, nextStateProps, {
662+
deepKeys: ['controlProps'],
663+
});
664+
},
665+
})(Control), ['controlProps'], ['mapProps']);
655666

656667
/* eslint-disable react/prop-types */
657-
const DefaultConnectedControl = (props) => (
658-
<ConnectedControl
659-
mapProps={{
660-
...controlPropsMap.default,
661-
...props.mapProps,
662-
}}
663-
{...omit(props, 'mapProps')}
664-
/>
665-
);
668+
/* eslint-disable react/no-multi-comp */
669+
class DefaultConnectedControl extends React.Component {
670+
shouldComponentUpdate(nextProps) {
671+
return !shallowEqual(this.props, nextProps, {
672+
deepKeys: ['controlProps'],
673+
omitKeys: ['mapProps'],
674+
});
675+
}
676+
677+
render() {
678+
return (
679+
<ConnectedControl
680+
mapProps={{
681+
...controlPropsMap.default,
682+
...this.props.mapProps,
683+
}}
684+
{...omit(this.props, 'mapProps')}
685+
/>
686+
);
687+
}
688+
}
666689

667690
DefaultConnectedControl.custom = ConnectedControl;
668691

669-
DefaultConnectedControl.input = (props) => (
670-
<ConnectedControl
671-
component="input"
672-
mapProps={{
673-
...controlPropsMap.default,
674-
...props.mapProps,
675-
}}
676-
{...omit(props, 'mapProps')}
677-
/>
678-
);
679-
680-
DefaultConnectedControl.text = (props) => (
681-
<ConnectedControl
682-
component="input"
683-
mapProps={{
684-
...controlPropsMap.text,
685-
type: 'text',
686-
...props.mapProps,
687-
}}
688-
{...omit(props, 'mapProps')}
689-
/>
690-
);
691-
692-
DefaultConnectedControl.textarea = (props) => (
693-
<ConnectedControl
694-
component="textarea"
695-
mapProps={{
696-
...controlPropsMap.textarea,
697-
...props.mapProps,
698-
}}
699-
{...omit(props, 'mapProps')}
700-
/>
701-
);
702-
703-
DefaultConnectedControl.radio = (props) => (
704-
<ConnectedControl
705-
component="input"
706-
type="radio"
707-
isToggle
708-
mapProps={{
709-
...controlPropsMap.radio,
710-
...props.mapProps,
711-
}}
712-
{...omit(props, 'mapProps')}
713-
/>
714-
);
715-
716-
DefaultConnectedControl.checkbox = (props) => (
717-
<ConnectedControl
718-
component="input"
719-
type="checkbox"
720-
isToggle
721-
mapProps={{
722-
...controlPropsMap.checkbox,
723-
...props.mapProps,
724-
}}
725-
getValue={getCheckboxValue}
726-
changeAction={props.changeAction || s.actions.checkWithValue}
727-
{...omit(props, 'mapProps')}
728-
/>
729-
);
730-
731-
DefaultConnectedControl.file = (props) => (
732-
<ConnectedControl
733-
component="input"
734-
type="file"
735-
mapProps={{
736-
...controlPropsMap.file,
737-
...props.mapProps,
738-
}}
739-
{...omit(props, 'mapProps')}
740-
/>
741-
);
742-
743-
DefaultConnectedControl.select = (props) => (
744-
<ConnectedControl
745-
component="select"
746-
mapProps={{
747-
...controlPropsMap.select,
748-
...props.mapProps,
749-
}}
750-
{...omit(props, 'mapProps')}
751-
/>
752-
);
753-
754-
DefaultConnectedControl.button = (props) => (
755-
<ConnectedControl
756-
component="button"
757-
mapProps={{
758-
...controlPropsMap.button,
759-
...props.mapProps,
760-
}}
761-
{...omit(props, 'mapProps')}
762-
/>
763-
);
764-
765-
DefaultConnectedControl.reset = (props) => (
766-
<ConnectedControl
767-
component="button"
768-
type="reset"
769-
mapProps={{
770-
...controlPropsMap.reset,
771-
...props.mapProps,
772-
}}
773-
{...omit(props, 'mapProps')}
774-
/>
775-
);
692+
class DefaultConnectedControlInput extends DefaultConnectedControl {
693+
render() {
694+
return (
695+
<ConnectedControl
696+
component="input"
697+
mapProps={{
698+
...controlPropsMap.default,
699+
...this.props.mapProps,
700+
}}
701+
{...omit(this.props, 'mapProps')}
702+
/>
703+
);
704+
}
705+
}
706+
707+
DefaultConnectedControl.input = DefaultConnectedControlInput;
708+
709+
class DefaultConnectedControlText extends DefaultConnectedControl {
710+
render() {
711+
return (
712+
<ConnectedControl
713+
component="input"
714+
mapProps={{
715+
...controlPropsMap.text,
716+
type: 'text',
717+
...this.props.mapProps,
718+
}}
719+
{...omit(this.props, 'mapProps')}
720+
/>
721+
);
722+
}
723+
}
724+
725+
DefaultConnectedControl.text = DefaultConnectedControlText;
726+
727+
class DefaultConnectedControlTextArea extends DefaultConnectedControl {
728+
render() {
729+
return (
730+
<ConnectedControl
731+
component="textarea"
732+
mapProps={{
733+
...controlPropsMap.textarea,
734+
...this.props.mapProps,
735+
}}
736+
{...omit(this.props, 'mapProps')}
737+
/>
738+
);
739+
}
740+
}
741+
742+
DefaultConnectedControl.textarea = DefaultConnectedControlTextArea;
743+
744+
class DefaultConnectedControlRadio extends DefaultConnectedControl {
745+
render() {
746+
return (
747+
<ConnectedControl
748+
component="input"
749+
type="radio"
750+
isToggle
751+
mapProps={{
752+
...controlPropsMap.radio,
753+
...this.props.mapProps,
754+
}}
755+
{...omit(this.props, 'mapProps')}
756+
/>
757+
);
758+
}
759+
}
760+
761+
DefaultConnectedControl.radio = DefaultConnectedControlRadio;
762+
763+
class DefaultConnectedControlCheckbox extends DefaultConnectedControl {
764+
render() {
765+
return (
766+
<ConnectedControl
767+
component="input"
768+
type="checkbox"
769+
isToggle
770+
mapProps={{
771+
...controlPropsMap.checkbox,
772+
...this.props.mapProps,
773+
}}
774+
getValue={getCheckboxValue}
775+
changeAction={this.props.changeAction || s.actions.checkWithValue}
776+
{...omit(this.props, 'mapProps')}
777+
/>
778+
);
779+
}
780+
}
781+
782+
DefaultConnectedControl.checkbox = DefaultConnectedControlCheckbox;
783+
784+
class DefaultConnectedControlFile extends DefaultConnectedControl {
785+
render() {
786+
return (
787+
<ConnectedControl
788+
component="input"
789+
type="file"
790+
mapProps={{
791+
...controlPropsMap.file,
792+
...this.props.mapProps,
793+
}}
794+
{...omit(this.props, 'mapProps')}
795+
/>
796+
);
797+
}
798+
}
799+
800+
DefaultConnectedControl.file = DefaultConnectedControlFile;
801+
802+
class DefaultConnectedControlSelect extends DefaultConnectedControl {
803+
render() {
804+
return (
805+
<ConnectedControl
806+
component="select"
807+
mapProps={{
808+
...controlPropsMap.select,
809+
...this.props.mapProps,
810+
}}
811+
{...omit(this.props, 'mapProps')}
812+
/>
813+
);
814+
}
815+
}
816+
817+
DefaultConnectedControl.select = DefaultConnectedControlSelect;
818+
819+
class DefaultConnectedControlButton extends DefaultConnectedControl {
820+
render() {
821+
return (
822+
<ConnectedControl
823+
component="button"
824+
mapProps={{
825+
...controlPropsMap.button,
826+
...this.props.mapProps,
827+
}}
828+
{...omit(this.props, 'mapProps')}
829+
/>
830+
);
831+
}
832+
}
833+
834+
DefaultConnectedControl.button = DefaultConnectedControlButton;
835+
836+
class DefaultConnectedControlReset extends DefaultConnectedControl {
837+
render() {
838+
return (
839+
<ConnectedControl
840+
component="button"
841+
type="reset"
842+
mapProps={{
843+
...controlPropsMap.reset,
844+
...this.props.mapProps,
845+
}}
846+
{...omit(this.props, 'mapProps')}
847+
/>
848+
);
849+
}
850+
}
851+
852+
DefaultConnectedControl.reset = DefaultConnectedControlReset;
776853

777854
return DefaultConnectedControl;
778855
}

src/utils/resolve-model.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,21 @@ function resolveModel(model, parentModel) {
1818
return model;
1919
}
2020

21-
export default function wrapWithModelResolver(WrappedComponent) {
21+
export default function wrapWithModelResolver(WrappedComponent, deepKeys = [], omitKeys = []) {
2222
class ResolvedModelWrapper extends ReactComponent {
2323
constructor(props, context) {
2424
super(props, context);
2525

2626
this.model = context.model;
2727
this.store = context.localStore;
28+
this.deepKeys = deepKeys;
29+
this.omitKeys = omitKeys;
2830
}
2931
shouldComponentUpdate(nextProps) {
30-
return !shallowEqual(this.props, nextProps);
32+
return !shallowEqual(this.props, nextProps, {
33+
deepKeys: this.deepKeys,
34+
omitKeys: this.omitKeys,
35+
});
3136
}
3237
render() {
3338
const resolvedModel = resolveModel(

0 commit comments

Comments
 (0)