Skip to content

Commit

Permalink
fix: edit mode performance improvements (#617)
Browse files Browse the repository at this point in the history
* fix: memoize items

* fix: only reproduce changed items

* fix: remove memoize-one

* fix: only memo in edit mode (view mode using local state: expanded item)

* fix: use lodash memoize

* fix: use memoizeOne for filters, remove unnecessary memoization of items
  • Loading branch information
janhenrikoverland authored Mar 10, 2020
1 parent 38ae5fc commit d8bcb58
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 41 deletions.
5 changes: 2 additions & 3 deletions src/components/Item/VisualizationItem/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withStyles } from '@material-ui/core/styles';
import uniqueId from 'lodash/uniqueId';
import VisualizationPlugin from '@dhis2/data-visualizer-plugin';

import i18n from '@dhis2/d2-i18n';
import uniqueId from 'lodash/uniqueId';

import DefaultPlugin from './DefaultPlugin';
import ItemHeader from '../ItemHeader';
Expand All @@ -24,11 +23,11 @@ import {
CHART,
REPORT_TABLE,
} from '../../../modules/itemTypes';
import memoizeOne from '../../../modules/memoizeOne';

import { colors } from '@dhis2/ui-core';
import { getVisualizationConfig } from './plugin';
import LoadingMask from './LoadingMask';
import memoizeOne from '../../../modules/memoizeOne';

const HEADER_HEIGHT = 45;

Expand Down
85 changes: 51 additions & 34 deletions src/components/ItemGrid/ItemGrid.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import memoize from 'lodash/memoize';
import i18n from '@dhis2/d2-i18n';
import ReactGridLayout from 'react-grid-layout';
import { CircularLoader, ScreenCover } from '@dhis2/ui-core';
Expand Down Expand Up @@ -49,6 +50,12 @@ export class ItemGrid extends Component {
expandedItems: {},
};

constructor(props) {
super(props);

this.getMemoizedItem = memoize(this.getItem);
}

onToggleItemExpanded = clickedId => {
const isExpanded =
typeof this.state.expandedItems[clickedId] === 'boolean'
Expand Down Expand Up @@ -91,6 +98,46 @@ export class ItemGrid extends Component {

onRemoveItemWrapper = id => () => this.onRemoveItem(id);

getItem = dashboardItem => {
const expandedItem = this.state.expandedItems[dashboardItem.id];
const hProp = { h: dashboardItem.h };

if (expandedItem && expandedItem === true) {
hProp.h = dashboardItem.h + EXPANDED_HEIGHT;
}

return Object.assign({}, dashboardItem, hProp, {
i: dashboardItem.id,
minH: ITEM_MIN_HEIGHT,
randomNumber: Math.random(),
});
};

getItems = dashboardItems =>
dashboardItems.map(item => this.getMemoizedItem(item));

getItemComponent = item => {
const itemClassNames = [
item.type,
this.props.edit ? 'edit' : 'view',
].join(' ');

return (
<ProgressiveLoadingContainer
key={item.i}
className={itemClassNames}
>
<Item
item={item}
editMode={this.props.edit}
onToggleItemExpanded={this.onToggleItemExpanded}
/>
</ProgressiveLoadingContainer>
);
};

getItemComponents = items => items.map(item => this.getItemComponent(item));

render() {
const { edit, isLoading, dashboardItems } = this.props;

Expand All @@ -102,19 +149,9 @@ export class ItemGrid extends Component {
);
}

const items = dashboardItems.map(item => {
const expandedItem = this.state.expandedItems[item.id];
const hProp = { h: item.h };

if (expandedItem && expandedItem === true) {
hProp.h = item.h + EXPANDED_HEIGHT;
}

return Object.assign({}, item, hProp, {
i: item.id,
minH: ITEM_MIN_HEIGHT,
});
});
const items = edit
? this.getItems(dashboardItems)
: dashboardItems.map(this.getItem);

return (
<div className="grid-wrapper">
Expand All @@ -137,27 +174,7 @@ export class ItemGrid extends Component {
isResizable={edit}
draggableCancel="input,textarea"
>
{items.map(item => {
const itemClassNames = [
item.type,
edit ? 'edit' : 'view',
].join(' ');

return (
<ProgressiveLoadingContainer
key={item.i}
className={itemClassNames}
>
<Item
item={item}
editMode={edit}
onToggleItemExpanded={
this.onToggleItemExpanded
}
/>
</ProgressiveLoadingContainer>
);
})}
{this.getItemComponents(items)}
</ReactGridLayout>
</div>
);
Expand Down
24 changes: 20 additions & 4 deletions src/reducers/editDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,32 @@ export default (state = DEFAULT_STATE_EDIT_DASHBOARD, action) => {
}
case RECEIVED_DASHBOARD_LAYOUT: {
const stateItems = orArray(state.dashboardItems);
let layoutHasChanged = false;

const newStateItems = action.value.map(({ x, y, w, h, i }) => {
const stateItem = stateItems.find(si => si.id === i);

return Object.assign({}, stateItem, { w, h, x, y });
if (
!(
stateItem.x === x &&
stateItem.y === y &&
stateItem.w === w &&
stateItem.h === h
)
) {
layoutHasChanged = true;
return Object.assign({}, stateItem, { w, h, x, y });
}

return stateItem;
});

return update(state, {
dashboardItems: { $set: newStateItems },
});
return layoutHasChanged
? {
...state,
dashboardItems: newStateItems,
}
: state;
}
case UPDATE_DASHBOARD_ITEM: {
const dashboardItem = action.value;
Expand Down

0 comments on commit d8bcb58

Please sign in to comment.