Skip to content

Commit 2633f3a

Browse files
authored
fix: improve resolver performance (#623)
1 parent b25469e commit 2633f3a

2 files changed

Lines changed: 50 additions & 23 deletions

File tree

‎.changeset/fluffy-days-act.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@craftjs/core': minor
3+
---
4+
5+
Improve resolver performance

‎packages/core/src/utils/resolveComponent.ts‎

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,60 @@
11
import { ERROR_NOT_IN_RESOLVER } from '@craftjs/utils';
2+
import React from 'react';
23
import invariant from 'tiny-invariant';
34

45
import { Resolver } from '../interfaces';
56

7+
type ReversedResolver = Map<React.ComponentType | string, string>;
8+
9+
type CachedResolverData = {
10+
resolver: Resolver;
11+
reversed: ReversedResolver;
12+
};
13+
14+
let CACHED_RESOLVER_DATA: CachedResolverData | null = null;
15+
16+
const getReversedResolver = (resolver: Resolver): ReversedResolver => {
17+
if (CACHED_RESOLVER_DATA && CACHED_RESOLVER_DATA.resolver === resolver) {
18+
return CACHED_RESOLVER_DATA.reversed;
19+
}
20+
21+
CACHED_RESOLVER_DATA = {
22+
resolver,
23+
reversed: new Map(),
24+
};
25+
26+
for (const [name, comp] of Object.entries(resolver)) {
27+
CACHED_RESOLVER_DATA.reversed.set(comp, name);
28+
}
29+
30+
return CACHED_RESOLVER_DATA.reversed;
31+
};
32+
33+
const getComponentName = (component: React.ElementType): string | undefined => {
34+
return (component as any).name || (component as any).displayName;
35+
};
36+
37+
const searchComponentInResolver = (
38+
resolver: Resolver,
39+
comp: React.ElementType
40+
): string | null => {
41+
const name = getReversedResolver(resolver).get(comp);
42+
return name !== undefined ? name : null;
43+
};
44+
645
export const resolveComponent = (
746
resolver: Resolver,
847
comp: React.ElementType | string
9-
) => {
10-
const componentName = (comp as any).name || (comp as any).displayName;
11-
12-
const getNameInResolver = () => {
13-
if (resolver[componentName]) {
14-
return componentName;
15-
}
16-
17-
for (let i = 0; i < Object.keys(resolver).length; i++) {
18-
const name = Object.keys(resolver)[i];
19-
const fn = resolver[name];
20-
21-
if (fn === comp) {
22-
return name;
23-
}
24-
}
25-
26-
if (typeof comp === 'string') {
27-
return comp;
28-
}
29-
};
48+
): string => {
49+
if (typeof comp === 'string') {
50+
return comp;
51+
}
3052

31-
const resolvedName = getNameInResolver();
53+
const resolvedName = searchComponentInResolver(resolver, comp);
3254

3355
invariant(
3456
resolvedName,
35-
ERROR_NOT_IN_RESOLVER.replace('%node_type%', componentName)
57+
ERROR_NOT_IN_RESOLVER.replace('%node_type%', getComponentName(comp))
3658
);
3759

3860
return resolvedName;

0 commit comments

Comments
 (0)