mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-22 17:10:26 +03:00
Memoized DefaultChart to make sure it does not change unless its props also change
This commit is contained in:
parent
039a56f410
commit
58ee123cef
3 changed files with 26 additions and 16 deletions
|
@ -14,5 +14,8 @@
|
|||
"process": true,
|
||||
"setImmediate": true
|
||||
},
|
||||
"ignorePatterns": ["src/service*.ts"]
|
||||
"ignorePatterns": ["src/service*.ts"],
|
||||
"rules": {
|
||||
"complexity": "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ const toDate = (date?: string | Date): Date | undefined => typeof date === 'stri
|
|||
export const ShortUrlForm = (
|
||||
TagsSelector: FC<TagsSelectorProps>,
|
||||
DomainSelector: FC<DomainSelectorProps>,
|
||||
): FC<ShortUrlFormProps> => ({ mode, saving, onSave, initialState, selectedServer }) => { // eslint-disable-line complexity
|
||||
): FC<ShortUrlFormProps> => ({ mode, saving, onSave, initialState, selectedServer }) => {
|
||||
const [ shortUrlData, setShortUrlData ] = useState(initialState);
|
||||
const isEdit = mode === 'edit';
|
||||
const changeTags = (tags: string[]) => setShortUrlData({ ...shortUrlData, tags: tags.map(normalizeTag) });
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from 'react';
|
||||
import { useState, memo } from 'react';
|
||||
import { Doughnut, Bar } from 'react-chartjs-2';
|
||||
import { keys, values } from 'ramda';
|
||||
import classNames from 'classnames';
|
||||
|
@ -53,7 +53,7 @@ const generateChartDatasets = (
|
|||
borderWidth: 2,
|
||||
};
|
||||
|
||||
if (!isBarChart) {
|
||||
if (!isBarChart || highlightedData.every((value) => value === 0)) {
|
||||
return [ mainDataset ];
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ const chartElementAtEvent = (
|
|||
|
||||
const statsAreDefined = (stats: Stats | undefined): stats is Stats => !!stats && Object.keys(stats).length > 0;
|
||||
|
||||
const DefaultChart = (
|
||||
const DefaultChart = memo((
|
||||
{ isBarChart = false, stats, max, highlightedStats, highlightedLabel, onClick }: DefaultChartProps,
|
||||
) => {
|
||||
const Component = isBarChart ? Bar : Doughnut;
|
||||
|
@ -150,20 +150,27 @@ const DefaultChart = (
|
|||
const chartData = generateChartData(isBarChart, labels, data, highlightedData, highlightedLabel);
|
||||
const height = determineHeight(isBarChart, labels);
|
||||
|
||||
const renderChartComponent = (customKey: string) => (
|
||||
<Component
|
||||
ref={(element) => {
|
||||
setChartRef(element ?? undefined);
|
||||
}}
|
||||
key={`${height}_${customKey}`}
|
||||
data={chartData}
|
||||
options={options}
|
||||
height={height}
|
||||
getElementAtEvent={chartElementAtEvent(labels, onClick) as any}
|
||||
/>
|
||||
);
|
||||
|
||||
// Provide a key based on the height, so that every time the dataset changes, a new chart is rendered
|
||||
return (
|
||||
<div className="row">
|
||||
<div className={classNames('col-sm-12', { 'col-md-7': !isBarChart })}>
|
||||
<Component
|
||||
ref={(element) => {
|
||||
setChartRef(element ?? undefined);
|
||||
}}
|
||||
key={height}
|
||||
data={chartData}
|
||||
options={options}
|
||||
height={height}
|
||||
getElementAtEvent={chartElementAtEvent(labels, onClick) as any}
|
||||
/>
|
||||
{/* It's VERY IMPORTANT to render two different components here, as one has 1 dataset and the other has 2 */}
|
||||
{/* Using the same component causes a crash when switching from 1 to 2 datasets, and then back to 1 dataset */}
|
||||
{highlightedStats !== undefined && renderChartComponent('with_stats')}
|
||||
{highlightedStats === undefined && renderChartComponent('without_stats')}
|
||||
</div>
|
||||
{!isBarChart && (
|
||||
<div className="col-sm-12 col-md-5">
|
||||
|
@ -172,6 +179,6 @@ const DefaultChart = (
|
|||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default DefaultChart;
|
||||
|
|
Loading…
Reference in a new issue