Skip to content

Commit a407cdf

Browse files
Upgrade React and Performance improvement
Performance improvements: * Add performance improvement for some graphs by adding useMemo Bugfixes: * Add bugfixes in barchart to show all labels even with missing data when labelOrder is mentioned Security update * Update react and react dom to 19.2.1
1 parent 5bd2e91 commit a407cdf

17 files changed

Lines changed: 364 additions & 166 deletions

File tree

package-lock.json

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@undp/data-viz",
3-
"version": "2.1.0",
3+
"version": "2.1.1",
44
"main": "./dist/index.cjs",
55
"module": "./dist/index.js",
66
"browser": "./dist/index.umd.js",
@@ -470,7 +470,7 @@
470470
"peerDependencies": {
471471
"@dnd-kit/core": "^6.3.1",
472472
"@dnd-kit/modifiers": "^9.0.0",
473-
"@undp/design-system-react": "^1.5.0",
473+
"@undp/design-system-react": "^1.5.1",
474474
"ajv": "^8.17.1",
475475
"dom-to-svg": "^0.12.2",
476476
"file-saver": "^2.0.5",
@@ -479,8 +479,8 @@
479479
"marked": "^16.4.1",
480480
"math-expression-evaluator": "^2.0.7",
481481
"pmtiles": "^4.3.0",
482-
"react": "^19.2.0",
483-
"react-dom": "^19.2.0",
482+
"react": "^19.2.1",
483+
"react-dom": "^19.2.1",
484484
"react-globe.gl": "^2.36.0",
485485
"tailwind-animate": "^0.2.10",
486486
"tailwind-merge": "^3.3.1",

src/Components/Graphs/BarGraph/GroupedBarGraph/Graph.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import isEqual from 'fast-deep-equal';
22
import { scaleLinear, scaleBand } from 'd3-scale';
3-
import { useRef, useState } from 'react';
3+
import { useMemo, useRef, useState } from 'react';
44
import { cn } from '@undp/design-system-react/cn';
55
import { AnimatePresence, motion, useInView } from 'motion/react';
66

@@ -128,11 +128,30 @@ export function HorizontalGraph(props: Props) {
128128
const graphWidth = width - margin.left - margin.right;
129129
const graphHeight = height - margin.top - margin.bottom;
130130

131-
const dataWithId = data.map((d, i) => ({
132-
...d,
133-
id: labelOrder ? `${d.label}` : `${i}`,
134-
}));
135-
const barOrder = labelOrder || dataWithId.map(d => `${d.id}`);
131+
const dataWithId = useMemo(() => {
132+
const idSet = new Set<string>();
133+
134+
const dataWithIdWithoutMissingIds = data.map((d, i) => {
135+
const id = labelOrder ? `${d.label}` : `${i}`;
136+
idSet.add(id);
137+
return { ...d, id };
138+
});
139+
140+
const missingIds = labelOrder ? labelOrder.filter(id => !idSet.has(id)) : [];
141+
142+
return [
143+
...dataWithIdWithoutMissingIds,
144+
...missingIds.map(id => ({
145+
id,
146+
label: id,
147+
size: Array(data[0].size.length).fill(null),
148+
})),
149+
];
150+
}, [data, labelOrder]);
151+
152+
const barOrder = useMemo(() => {
153+
return labelOrder ?? dataWithId.map(d => `${d.id}`);
154+
}, [labelOrder, dataWithId]);
136155

137156
const x = scaleLinear().domain([minValue, maxValue]).range([0, graphWidth]).nice();
138157
const y = scaleBand()
@@ -436,13 +455,33 @@ export function VerticalGraph(props: Props) {
436455
const graphWidth = width - margin.left - margin.right;
437456
const graphHeight = height - margin.top - margin.bottom;
438457

458+
const dataWithId = useMemo(() => {
459+
const idSet = new Set<string>();
460+
461+
const dataWithIdWithoutMissingIds = data.map((d, i) => {
462+
const id = labelOrder ? `${d.label}` : `${i}`;
463+
idSet.add(id);
464+
return { ...d, id };
465+
});
466+
467+
const missingIds = labelOrder ? labelOrder.filter(id => !idSet.has(id)) : [];
468+
469+
return [
470+
...dataWithIdWithoutMissingIds,
471+
...missingIds.map(id => ({
472+
id,
473+
label: id,
474+
size: Array(data[0].size.length).fill(null),
475+
})),
476+
];
477+
}, [data, labelOrder]);
478+
479+
const barOrder = useMemo(() => {
480+
return labelOrder ?? dataWithId.map(d => `${d.id}`);
481+
}, [labelOrder, dataWithId]);
482+
439483
const y = scaleLinear().domain([minValue, maxValue]).range([graphHeight, 0]).nice();
440484

441-
const dataWithId = data.map((d, i) => ({
442-
...d,
443-
id: labelOrder ? `${d.label}` : `${i}`,
444-
}));
445-
const barOrder = labelOrder || dataWithId.map(d => `${d.id}`);
446485
const x = scaleBand()
447486
.domain(barOrder)
448487
.range([

src/Components/Graphs/BarGraph/GroupedBarGraph/index.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { useState, useRef, useEffect } from 'react';
1+
import { useState, useRef, useEffect, useMemo } from 'react';
22
import { SliderUI } from '@undp/design-system-react/SliderUI';
33
import { format } from 'date-fns/format';
44
import { parse } from 'date-fns/parse';
5-
import { ascending, sort } from 'd3-array';
65
import orderBy from 'lodash.orderby';
76
import sum from 'lodash.sum';
87

@@ -28,7 +27,6 @@ import { checkIfNullOrUndefined } from '@/Utils/checkIfNullOrUndefined';
2827
import { Pause, Play } from '@/Components/Icons';
2928
import { getSliderMarks } from '@/Utils/getSliderMarks';
3029
import { ensureCompleteDataForStackedBarChart } from '@/Utils/ensureCompleteData';
31-
import { uniqBy } from '@/Utils/uniqBy';
3230
import { GraphArea, GraphContainer } from '@/Components/Elements/GraphContainer';
3331

3432
interface Props {
@@ -158,12 +156,13 @@ export function GroupedBarGraphEl(props: Props) {
158156
const [svgWidth, setSvgWidth] = useState(0);
159157
const [svgHeight, setSvgHeight] = useState(0);
160158
const [play, setPlay] = useState(timeline.autoplay);
161-
const uniqDatesSorted = sort(
162-
uniqBy(data, 'date', true).map(d =>
163-
parse(`${d}`, timeline.dateFormat || 'yyyy', new Date()).getTime(),
164-
),
165-
(a, b) => ascending(a, b),
166-
);
159+
const uniqDatesSorted = useMemo(() => {
160+
const dates = [
161+
...new Set(data.map(d => parse(`${d}`, timeline.dateFormat || 'yyyy', new Date()).getTime())),
162+
];
163+
dates.sort((a, b) => a - b);
164+
return dates;
165+
}, [data, timeline.dateFormat]);
167166
const [index, setIndex] = useState(timeline.autoplay ? 0 : uniqDatesSorted.length - 1);
168167
const [selectedColor, setSelectedColor] = useState<string | undefined>(undefined);
169168

src/Components/Graphs/BarGraph/SimpleBarGraph/Graph.tsx

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import isEqual from 'fast-deep-equal';
22
import { scaleLinear, scaleBand } from 'd3-scale';
3-
import { useRef, useState } from 'react';
3+
import { useMemo, useRef, useState } from 'react';
44
import { cn } from '@undp/design-system-react/cn';
55
import { AnimatePresence, motion, useInView } from 'motion/react';
66

@@ -135,12 +135,33 @@ export function HorizontalGraph(props: Props) {
135135
const graphWidth = width - margin.left - margin.right;
136136
const graphHeight = height - margin.top - margin.bottom;
137137

138-
const dataWithId = data.map((d, i) => ({
139-
...d,
140-
id: labelOrder ? `${d.label}` : `${i}`,
141-
}));
138+
const dataWithId = useMemo(() => {
139+
const idSet = new Set<string>();
140+
141+
const dataWithIdWithoutMissingIds = data.map((d, i) => {
142+
const id = labelOrder ? `${d.label}` : `${i}`;
143+
idSet.add(id);
144+
return { ...d, id };
145+
});
146+
147+
const missingIds = labelOrder ? labelOrder.filter(id => !idSet.has(id)) : [];
148+
149+
return [
150+
...dataWithIdWithoutMissingIds,
151+
...missingIds.map(id => ({
152+
id,
153+
label: id,
154+
color: null,
155+
size: null,
156+
})),
157+
];
158+
}, [data, labelOrder]);
159+
160+
const barOrder = useMemo(() => {
161+
return labelOrder ?? dataWithId.map(d => `${d.id}`);
162+
}, [labelOrder, dataWithId]);
163+
142164
const x = scaleLinear().domain([minValue, maxValue]).range([0, graphWidth]).nice();
143-
const barOrder = labelOrder || dataWithId.map(d => `${d.id}`);
144165
const y = scaleBand()
145166
.domain(barOrder)
146167
.range([
@@ -485,13 +506,34 @@ export function VerticalGraph(props: Props) {
485506
const graphWidth = width - margin.left - margin.right;
486507
const graphHeight = height - margin.top - margin.bottom;
487508

509+
const dataWithId = useMemo(() => {
510+
const idSet = new Set<string>();
511+
512+
const dataWithIdWithoutMissingIds = data.map((d, i) => {
513+
const id = labelOrder ? `${d.label}` : `${i}`;
514+
idSet.add(id);
515+
return { ...d, id };
516+
});
517+
518+
const missingIds = labelOrder ? labelOrder.filter(id => !idSet.has(id)) : [];
519+
520+
return [
521+
...dataWithIdWithoutMissingIds,
522+
...missingIds.map(id => ({
523+
id,
524+
label: id,
525+
color: null,
526+
size: null,
527+
})),
528+
];
529+
}, [data, labelOrder]);
530+
531+
const barOrder = useMemo(() => {
532+
return labelOrder ?? dataWithId.map(d => `${d.id}`);
533+
}, [labelOrder, dataWithId]);
534+
488535
const y = scaleLinear().domain([minValue, maxValue]).range([graphHeight, 0]).nice();
489536

490-
const dataWithId = data.map((d, i) => ({
491-
...d,
492-
id: labelOrder ? `${d.label}` : `${i}`,
493-
}));
494-
const barOrder = labelOrder || dataWithId.map(d => `${d.id}`);
495537
const x = scaleBand()
496538
.domain(barOrder)
497539
.range([

src/Components/Graphs/BarGraph/SimpleBarGraph/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { useState, useRef, useEffect } from 'react';
1+
import { useState, useRef, useEffect, useMemo } from 'react';
22
import { format } from 'date-fns/format';
33
import { parse } from 'date-fns/parse';
44
import { SliderUI } from '@undp/design-system-react/SliderUI';
5-
import { ascending, sort } from 'd3-array';
65
import orderBy from 'lodash.orderby';
76

87
import { HorizontalGraph, VerticalGraph } from './Graph';
@@ -164,12 +163,13 @@ export function SimpleBarGraphEl(props: Props) {
164163
const [svgWidth, setSvgWidth] = useState(0);
165164
const [svgHeight, setSvgHeight] = useState(0);
166165
const [play, setPlay] = useState(timeline.autoplay);
167-
const uniqDatesSorted = sort(
168-
uniqBy(data, 'date', true).map(d =>
169-
parse(`${d}`, timeline.dateFormat || 'yyyy', new Date()).getTime(),
170-
),
171-
(a, b) => ascending(a, b),
172-
);
166+
const uniqDatesSorted = useMemo(() => {
167+
const dates = [
168+
...new Set(data.map(d => parse(`${d}`, timeline.dateFormat || 'yyyy', new Date()).getTime())),
169+
];
170+
dates.sort((a, b) => a - b);
171+
return dates;
172+
}, [data, timeline.dateFormat]);
173173
const [index, setIndex] = useState(timeline.autoplay ? 0 : uniqDatesSorted.length - 1);
174174
const [selectedColor, setSelectedColor] = useState<string | undefined>(undefined);
175175

0 commit comments

Comments
 (0)