Skip to content

Commit f3d4629

Browse files
committed
Collection: Internal data structure changes
1 parent 8fe4a28 commit f3d4629

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

.changeset/wicked-pens-call.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@radix-ui/react-collection': patch
3+
---
4+
5+
Internal changes to collection to use OrderedDict structure

packages/react/collection/src/collection-legacy.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { createContextScope } from '@radix-ui/react-context';
33
import { useComposedRefs } from '@radix-ui/react-compose-refs';
44
import { createSlot, type Slot } from '@radix-ui/react-slot';
5+
import { OrderedDict } from './ordered-dictionary';
56

67
type SlotProps = React.ComponentPropsWithoutRef<typeof Slot>;
78
type CollectionElement = HTMLElement;
@@ -11,7 +12,7 @@ interface CollectionProps extends SlotProps {
1112

1213
// We have resorted to returning slots directly rather than exposing primitives that can then
1314
// be slotted like `<CollectionItem as={Slot}>…</CollectionItem>`.
14-
// This is because we encountered issues with generic types that cannot be statically analysed
15+
// This is because we encountered issues with generic types that cannot be statically analyzed
1516
// due to creating them dynamically via createCollection.
1617

1718
function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name: string) {
@@ -22,23 +23,25 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
2223
const PROVIDER_NAME = name + 'CollectionProvider';
2324
const [createCollectionContext, createCollectionScope] = createContextScope(PROVIDER_NAME);
2425

26+
type ItemMap = OrderedDict<
27+
React.RefObject<ItemElement | null>,
28+
{ ref: React.RefObject<ItemElement | null> } & ItemData
29+
>;
30+
2531
type ContextValue = {
2632
collectionRef: React.RefObject<CollectionElement | null>;
27-
itemMap: Map<
28-
React.RefObject<ItemElement | null>,
29-
{ ref: React.RefObject<ItemElement | null> } & ItemData
30-
>;
33+
itemMap: React.RefObject<ItemMap>;
3134
};
3235

3336
const [CollectionProviderImpl, useCollectionContext] = createCollectionContext<ContextValue>(
3437
PROVIDER_NAME,
35-
{ collectionRef: { current: null }, itemMap: new Map() },
38+
{ collectionRef: { current: null }, itemMap: { current: new OrderedDict() } },
3639
);
3740

3841
const CollectionProvider: React.FC<{ children?: React.ReactNode; scope: any }> = (props) => {
3942
const { scope, children } = props;
4043
const ref = React.useRef<CollectionElement>(null);
41-
const itemMap = React.useRef<ContextValue['itemMap']>(new Map()).current;
44+
const itemMap = React.useRef<ItemMap>(new OrderedDict());
4245
return (
4346
<CollectionProviderImpl scope={scope} itemMap={itemMap} collectionRef={ref}>
4447
{children}
@@ -87,8 +90,8 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
8790
const context = useCollectionContext(ITEM_SLOT_NAME, scope);
8891

8992
React.useEffect(() => {
90-
context.itemMap.set(ref, { ref, ...(itemData as unknown as ItemData) });
91-
return () => void context.itemMap.delete(ref);
93+
context.itemMap.current.set(ref, { ref, ...(itemData as unknown as ItemData) });
94+
return () => void context.itemMap.current.delete(ref);
9295
});
9396

9497
return (
@@ -112,11 +115,10 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
112115
const collectionNode = context.collectionRef.current;
113116
if (!collectionNode) return [];
114117
const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
115-
const items = Array.from(context.itemMap.values());
116-
const orderedItems = items.sort(
117-
(a, b) => orderedNodes.indexOf(a.ref.current!) - orderedNodes.indexOf(b.ref.current!),
118+
const items = context.itemMap.current.toSorted(
119+
(a, b) => orderedNodes.indexOf(a[0].current!) - orderedNodes.indexOf(b[0].current!),
118120
);
119-
return orderedItems;
121+
return Array.from(items.values());
120122
}, [context.collectionRef, context.itemMap]);
121123

122124
return getItems;

0 commit comments

Comments
 (0)