Skip to content

Commit c23efbb

Browse files
committed
ColorHelper performance optimization
1 parent 9e4ad50 commit c23efbb

File tree

5 files changed

+138
-52
lines changed

5 files changed

+138
-52
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
"storybook-dark-mode": "^1.1.2",
109109
"ts-node": "^10.9.1",
110110
"tss-react": "^4.4.4",
111+
"type-route": "^1.0.1",
111112
"typescript": "^4.9.1-beta",
112113
"vitest": "^0.24.3"
113114
},

src/tools/memoize.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
1-
export function memoize<Args extends (number | boolean | string)[], R>(
2-
fn: (...args: Args) => R,
1+
type SimpleType = number | string | boolean | null | undefined;
2+
type FuncWithSimpleParams<T extends SimpleType[]> = (...args: T) => any;
3+
4+
export function memoize<T extends SimpleType[]>(
5+
fn: FuncWithSimpleParams<T>,
36
options?: {
47
argsLength?: number;
58
max?: number;
69
}
7-
): (...args: Args) => R {
8-
const cache = new Map<string, R>();
10+
): FuncWithSimpleParams<T> {
11+
const cache = new Map<string, ReturnType<FuncWithSimpleParams<T>>>();
912

1013
const { argsLength = fn.length, max = Infinity } = options ?? {};
1114

12-
return ((...args: Args) => {
13-
const key = JSON.stringify(args.slice(0, argsLength).join("-sIs9sAslOdeWlEdIos3-"));
15+
return ((...args: Parameters<FuncWithSimpleParams<T>>) => {
16+
const key = JSON.stringify(
17+
args
18+
.slice(0, argsLength)
19+
.map(v => {
20+
if (v === null) {
21+
return "null";
22+
}
23+
if (v === undefined) {
24+
return "undefined";
25+
}
26+
switch (typeof v) {
27+
case "number":
28+
return `number-${v}`;
29+
case "string":
30+
return `string-${v}`;
31+
case "boolean":
32+
return `boolean-${v ? "true" : "false"}`;
33+
}
34+
})
35+
.join("-sIs9sAslOdeWlEdIos3-")
36+
);
1437

1538
if (cache.has(key)) {
1639
return cache.get(key);

stories/ColorHelper/ColorHelper.tsx

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useTransition, useRef } from "react";
1+
import React, { useState, useRef } from "react";
22
import { CallOut } from "../../dist/CallOut";
33
import { colorDecisionAndCorrespondingOptions } from "../../dist/fr/generatedFromCss/colorDecisionAndCorrespondingOptions";
44
import type { ColorDecisionAndCorrespondingOption } from "../../src/scripts/build/cssToTs/colorDecisionAndCorrespondingOptions";
@@ -34,7 +34,8 @@ export function ColorHelper() {
3434
const updateFilter = () =>
3535
setFilteredColorDecisionAndCorrespondingOption(
3636
filterColorDecisionAndCorrespondingOption({
37-
search,
37+
search
38+
})({
3839
context,
3940
color,
4041
usage
@@ -43,18 +44,32 @@ export function ColorHelper() {
4344

4445
useDebounce(() => updateFilter(), [search]);
4546

46-
{
47-
const [, startTransition] = useTransition();
48-
49-
useEffectOnValueChange(() => {
50-
startTransition(() => updateFilter());
51-
}, [context, color, usage]);
52-
}
47+
useEffectOnValueChange(() => {
48+
updateFilter();
49+
}, [context, color, usage]);
5350

5451
const { css } = useStyles();
5552

5653
const evtSearchAction = useConst(() => Evt.create<"scroll to">());
5754

55+
const [filteredContextes, setFilteredContextes] = useState(contextes);
56+
57+
useEffectOnValueChange(() => {
58+
const f = filterColorDecisionAndCorrespondingOption({ search });
59+
60+
setFilteredContextes(
61+
contextes.filter(context => f({ context, color, usage }).length !== 0)
62+
);
63+
}, [search, context, color, usage]);
64+
65+
const [filteredColors, setFilteredColors] = useState(colors);
66+
67+
useEffectOnValueChange(() => {
68+
const f = filterColorDecisionAndCorrespondingOption({ search });
69+
70+
setFilteredColors(colors.filter(color => f({ context, color, usage }).length !== 0));
71+
}, [search, context, color, usage]);
72+
5873
return (
5974
<MuiDsfrThemeProvider>
6075
<div>
@@ -78,37 +93,26 @@ export function ColorHelper() {
7893
evtAction={evtSearchAction}
7994
onSearchChange={search => setSearch(search)}
8095
search={search}
81-
contextes={contextes.filter(
82-
context =>
83-
filterColorDecisionAndCorrespondingOption({
84-
search,
85-
context,
86-
color,
87-
usage
88-
}).length !== 0
89-
)}
96+
contextes={filteredContextes}
9097
context={context}
9198
onContextChange={setContext}
92-
colors={colors.filter(
93-
color =>
94-
filterColorDecisionAndCorrespondingOption({
95-
search,
96-
context,
97-
color,
98-
usage
99-
}).length !== 0
100-
)}
99+
colors={filteredColors}
101100
color={color}
102101
onColorChange={setColor}
103-
usages={usages.filter(
102+
usages={
103+
[]
104+
/*
105+
usages.filter(
104106
usage =>
105107
filterColorDecisionAndCorrespondingOption({
106108
search,
107109
context,
108110
color,
109111
usage
110112
}).length !== 0
111-
)}
113+
)
114+
*/
115+
}
112116
usage={usage}
113117
onUsageChange={setUsage}
114118
/>
@@ -241,29 +245,34 @@ const { filterColorDecisionAndCorrespondingOption } = (() => {
241245
}
242246
);
243247

244-
function filterColorDecisionAndCorrespondingOption(params: {
245-
search: string;
246-
context: SearchProps["context"] | undefined;
247-
color: SearchProps["color"] | undefined;
248-
usage: SearchProps["usage"] | undefined;
249-
}) {
250-
const { search, context, color, usage } = params;
248+
function filterColorDecisionAndCorrespondingOption(params: { search: string }) {
249+
const { search } = params;
251250

252-
return fzf
251+
const filteredColorDecisionAndCorrespondingOptions = fzf
253252
.find(search)
254253
.map(
255254
({ item: colorDecisionAndCorrespondingOption }) =>
256255
colorDecisionAndCorrespondingOption
257-
)
258-
.filter(({ parsedColorDecisionName }) =>
259-
context === undefined ? true : parsedColorDecisionName.context === context
260-
)
261-
.filter(({ parsedColorDecisionName }) =>
262-
color === undefined ? true : parsedColorDecisionName.colorName === color
263-
)
264-
.filter(({ parsedColorDecisionName }) =>
265-
usage === undefined ? true : parsedColorDecisionName.usage === usage
266256
);
257+
258+
return (params: {
259+
context: SearchProps["context"] | undefined;
260+
color: SearchProps["color"] | undefined;
261+
usage: SearchProps["usage"] | undefined;
262+
}) => {
263+
const { context, color, usage } = params;
264+
265+
return filteredColorDecisionAndCorrespondingOptions
266+
.filter(({ parsedColorDecisionName }) =>
267+
context === undefined ? true : parsedColorDecisionName.context === context
268+
)
269+
.filter(({ parsedColorDecisionName }) =>
270+
color === undefined ? true : parsedColorDecisionName.colorName === color
271+
)
272+
.filter(({ parsedColorDecisionName }) =>
273+
usage === undefined ? true : parsedColorDecisionName.usage === usage
274+
);
275+
};
267276
}
268277

269278
return { filterColorDecisionAndCorrespondingOption };
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { useState } from "react";
2+
3+
const getQuery = () => {
4+
if (typeof window !== "undefined") {
5+
return new URLSearchParams(window.location.search);
6+
}
7+
return new URLSearchParams();
8+
};
9+
10+
const getQueryStringVal = (key: string): string | null => {
11+
return getQuery().get(key);
12+
};
13+
14+
export const useQueryParam = (key: string, defaultVal: string): [string, (val: string) => void] => {
15+
const [query, setQuery] = useState(getQueryStringVal(key) || defaultVal);
16+
17+
const updateUrl = (newVal: string) => {
18+
setQuery(newVal);
19+
20+
const query = getQuery();
21+
22+
if (newVal.trim() !== "") {
23+
query.set(key, newVal);
24+
} else {
25+
query.delete(key);
26+
}
27+
28+
// This check is necessary if using the hook with Gatsby
29+
if (typeof window !== "undefined") {
30+
const { protocol, pathname, host } = window.location;
31+
const newUrl = `${protocol}//${host}${pathname}?${query.toString()}`;
32+
window.history.pushState({}, "", newUrl);
33+
}
34+
};
35+
36+
return [query, updateUrl];
37+
};
38+
39+
export default useQueryParam;

yarn.lock

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6740,6 +6740,13 @@ he@^1.2.0:
67406740
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
67416741
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
67426742

6743+
history@^5.3.0:
6744+
version "5.3.0"
6745+
resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
6746+
integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
6747+
dependencies:
6748+
"@babel/runtime" "^7.7.6"
6749+
67436750
hmac-drbg@^1.0.1:
67446751
version "1.0.1"
67456752
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -11044,6 +11051,13 @@ type-is@~1.6.18:
1104411051
media-typer "0.3.0"
1104511052
mime-types "~2.1.24"
1104611053

11054+
type-route@^1.0.1:
11055+
version "1.0.1"
11056+
resolved "https://registry.yarnpkg.com/type-route/-/type-route-1.0.1.tgz#02164dddc72e62dbb88d083e539137279cdd5deb"
11057+
integrity sha512-8mVNfsQeMxlG2BoSU//VrDjNo74NeKAEI9p/7BH6H1VMYFJF8MgM+Q1eeTu1UsjZtr7jGA1whHVUe82fJb0V8w==
11058+
dependencies:
11059+
history "^5.3.0"
11060+
1104711061
type@^1.0.1:
1104811062
version "1.2.0"
1104911063
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"

0 commit comments

Comments
 (0)