Skip to content

Commit

Permalink
perf(react-scheduler): optimize render using React.memo (#2169)
Browse files Browse the repository at this point in the history
  • Loading branch information
AryamnovEugeniy committed Jul 30, 2019
1 parent 005336b commit 52a877c
Show file tree
Hide file tree
Showing 16 changed files with 68 additions and 49 deletions.
Expand Up @@ -29,7 +29,7 @@ const styles = theme => ({
},
});

export const TitleCellBase = ({
export const TitleCellBase = React.memo(({
classes, getMessage, className, ...restProps
}) => (
<div className={classNames(classes.container, className)} {...restProps}>
Expand All @@ -39,7 +39,7 @@ export const TitleCellBase = ({
</Typography>
</div>
</div>
);
));

TitleCellBase.propTypes = {
classes: PropTypes.object.isRequired,
Expand Down
Expand Up @@ -45,7 +45,7 @@ const styles = {
},
};

const SplitIndicatorBase = ({
const SplitIndicatorBase = React.memo(({
position, appointmentType, classes, className, ...restProps
}) => {
const vertical = appointmentType === VERTICAL_TYPE;
Expand All @@ -62,7 +62,7 @@ const SplitIndicatorBase = ({
{...restProps}
/>
);
};
});

SplitIndicatorBase.propTypes = {
classes: PropTypes.object.isRequired,
Expand Down
Expand Up @@ -4,7 +4,7 @@ import IconButton from '@material-ui/core/IconButton';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';

export const NavigationButton = ({
export const NavigationButton = React.memo(({
type,
onClick,
...restProps
Expand All @@ -15,7 +15,7 @@ export const NavigationButton = ({
>
{type === 'back' ? <ChevronLeft /> : <ChevronRight />}
</IconButton>
);
));

NavigationButton.propTypes = {
type: PropTypes.oneOf(['forward', 'back']).isRequired,
Expand Down
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import * as PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';

export const OpenButton = ({
export const OpenButton = React.memo(({
text, onVisibilityToggle, ...restProps
}) => (
<Button
Expand All @@ -11,7 +11,7 @@ export const OpenButton = ({
>
{text}
</Button>
);
));

OpenButton.propTypes = {
onVisibilityToggle: PropTypes.func.isRequired,
Expand Down
Expand Up @@ -22,26 +22,31 @@ const RootBase = ({
className,
classes,
...restProps
}) => (
<div
className={classNames(classes.root, className)}
ref={rootRef}
{...restProps}
>
<NavigationButton
type="back"
onClick={() => { onNavigate('back'); }}
/>
<NavigationButton
type="forward"
onClick={() => { onNavigate('forward'); }}
/>
<OpenButton
onVisibilityToggle={onVisibilityToggle}
text={navigatorText}
/>
</div>
);
}) => {
const navigateBack = React.useCallback(() => onNavigate('back'), [onNavigate]);
const navigateForward = React.useCallback(() => onNavigate('forward'), [onNavigate]);

return (
<div
className={classNames(classes.root, className)}
ref={rootRef}
{...restProps}
>
<NavigationButton
type="back"
onClick={navigateBack}
/>
<NavigationButton
type="forward"
onClick={navigateForward}
/>
<OpenButton
onVisibilityToggle={onVisibilityToggle}
text={navigatorText}
/>
</div>
);
};

RootBase.propTypes = {
// oneOfType is a workaround because withStyles returns react object
Expand Down
Expand Up @@ -46,7 +46,7 @@ const styles = ({ spacing }) => {
});
};

const ResizeBase = ({
const ResizeBase = React.memo(({
classes, className,
position, appointmentType, ...restProps
}) => {
Expand All @@ -64,7 +64,7 @@ const ResizeBase = ({
{...restProps}
/>
);
};
});


ResizeBase.propTypes = {
Expand Down
Expand Up @@ -26,7 +26,7 @@ const styles = ({ spacing, typography }) => ({
},
});

const SwitcherBase = ({
const SwitcherBase = React.memo(({
currentView,
availableViews,
onChange, classes,
Expand Down Expand Up @@ -60,7 +60,7 @@ const SwitcherBase = ({
))}
</Select>
);
};
});

SwitcherBase.propTypes = {
onChange: PropTypes.func.isRequired,
Expand Down
Expand Up @@ -22,7 +22,7 @@ const styles = theme => ({
},
});

const CellBase = ({
const CellBase = React.memo(({
classes,
className,
startDate,
Expand All @@ -39,7 +39,7 @@ const CellBase = ({
{formatDate(startDate, WEEK_DAY_OPTIONS)}
</div>
</TableCell>
);
));

CellBase.propTypes = {
classes: PropTypes.object.isRequired,
Expand Down
Expand Up @@ -48,7 +48,7 @@ const styles = theme => ({
},
});

const CellBase = ({
const CellBase = React.memo(({
classes,
className,
startDate,
Expand All @@ -73,7 +73,7 @@ const CellBase = ({
{formatDate(startDate, DAY_OPTIONS)}
</div>
</TableCell>
);
));

CellBase.propTypes = {
classes: PropTypes.object.isRequired,
Expand Down
Expand Up @@ -24,7 +24,7 @@ const styles = theme => ({
},
});

const CellBase = ({
const CellBase = React.memo(({
classes,
className,
startDate,
Expand Down Expand Up @@ -54,7 +54,7 @@ const CellBase = ({
{formatDate(startDate, DAY_OPTIONS)}
</span>
</TableCell>
);
));

CellBase.propTypes = {
classes: PropTypes.object.isRequired,
Expand Down
Expand Up @@ -25,7 +25,7 @@ const styles = theme => ({
},
});

const CellBase = ({
const CellBase = React.memo(({
classes,
className,
startDate,
Expand All @@ -41,7 +41,7 @@ const CellBase = ({
{formatDate(endDate, HOUR_MINUTE_OPTIONS)}
</span>
</TableCell>
);
));

CellBase.propTypes = {
formatDate: PropTypes.func.isRequired,
Expand Down
5 changes: 4 additions & 1 deletion packages/dx-react-scheduler/src/plugins/all-day-panel.tsx
Expand Up @@ -59,6 +59,9 @@ class AllDayPanelBase extends React.PureComponent<AllDayPanelProps, AllDayPanelS
this.setState({ rects, elementsMeta: cellElementsMeta });
});

getMessageFormatter = memoize((messages, allDayPanelDefaultMessages) =>
getMessagesFormatter({ ...allDayPanelDefaultMessages, ...messages }));

render() {
const {
appointmentLayerComponent: AppointmentLayer,
Expand All @@ -70,7 +73,7 @@ class AllDayPanelBase extends React.PureComponent<AllDayPanelProps, AllDayPanelS
messages,
} = this.props;
const { rects, elementsMeta } = this.state;
const getMessage = getMessagesFormatter({ ...defaultMessages, ...messages });
const getMessage = this.getMessageFormatter(messages, defaultMessages);

return (
<Plugin
Expand Down
8 changes: 7 additions & 1 deletion packages/dx-react-scheduler/src/plugins/date-navigator.tsx
Expand Up @@ -10,6 +10,7 @@ import {
monthCellsData,
viewBoundText,
} from '@devexpress/dx-scheduler-core';
import { memoize } from '@devexpress/dx-core';

import { DateNavigatorProps, DateNavigatorState } from '../types';

Expand Down Expand Up @@ -58,6 +59,9 @@ class DateNavigatorBase extends React.PureComponent<DateNavigatorProps, DateNavi
this.setState({ visible: false });
}

navigateAction = memoize((changeCurrentDate, currentView, intervalCount, navigateAction) =>
navigateAction(changeCurrentDate, currentView, intervalCount));

render() {
const {
rootComponent: Root,
Expand Down Expand Up @@ -93,7 +97,9 @@ class DateNavigatorBase extends React.PureComponent<DateNavigatorProps, DateNavi
}, {
changeCurrentDate,
}) => {
const navigateAction = navigate(changeCurrentDate, currentView, intervalCount);
const navigateAction = this.navigateAction(
changeCurrentDate, currentView, intervalCount, navigate,
);
const calendarDateChanged = (nextDate) => {
navigateAction(undefined, nextDate);
this.handleHide();
Expand Down
3 changes: 3 additions & 0 deletions packages/dx-react-scheduler/src/plugins/scheduler-core.tsx
Expand Up @@ -4,8 +4,11 @@ import {
} from '@devexpress/dx-react-core';
import { appointments, formatDateTimeGetter } from '@devexpress/dx-scheduler-core';
import { SchedulerProps } from '../types';
import { memoize } from '@devexpress/dx-core';

class SchedulerCoreBase extends React.PureComponent<SchedulerProps> {
formatDateTimeGetter = memoize(locale => formatDateTimeGetter(locale));

render() {
const {
data,
Expand Down
15 changes: 8 additions & 7 deletions packages/dx-react-scheduler/src/plugins/view-state.tsx
Expand Up @@ -6,14 +6,14 @@ import {
createStateHelper,
StateHelper,
ActionFn,
ComputedFn,
} from '@devexpress/dx-react-core';
import {
changeCurrentDate,
setCurrentViewName,
ChangeCurrentDatePayload,
} from '@devexpress/dx-scheduler-core';
import { ViewStateProps, ViewStateState } from '../types';
import { memoize } from '@devexpress/dx-core';

class ViewStateBase extends React.PureComponent<ViewStateProps, ViewStateState> {
changeCurrentDate: ActionFn<ChangeCurrentDatePayload>;
Expand Down Expand Up @@ -63,19 +63,20 @@ class ViewStateBase extends React.PureComponent<ViewStateProps, ViewStateState>
};
}

getCurrentViewComputed = memoize(currentViewName => () => (
currentViewName
? { name: currentViewName }
: undefined
));

render() {
const { currentDate, currentViewName: stateCurrentViewName } = this.state;
const currentViewComputed: ComputedFn = () => (
stateCurrentViewName
? { name: stateCurrentViewName }
: undefined
);
return (
<Plugin
name="ViewState"
>
<Getter name="currentDate" value={currentDate} />
<Getter name="currentView" computed={currentViewComputed} />
<Getter name="currentView" computed={this.getCurrentViewComputed(stateCurrentViewName)} />
<Action name="changeCurrentDate" action={this.changeCurrentDate} />
<Action name="setCurrentViewName" action={this.setCurrentViewName} />
</Plugin>
Expand Down
1 change: 1 addition & 0 deletions packages/dx-react-scheduler/src/plugins/view-switcher.tsx
Expand Up @@ -17,6 +17,7 @@ class ViewSwitcherBase extends React.PureComponent<ViewSwitcherProps> {
static components: PluginComponents = {
switcherComponent: 'Switcher',
};

render() {
const { switcherComponent: Switcher } = this.props;

Expand Down

0 comments on commit 52a877c

Please sign in to comment.