Skip to content

Commit

Permalink
change: For item component takes an item$ parameter instead of item
Browse files Browse the repository at this point in the history
  • Loading branch information
jmeistrich committed Oct 8, 2023
1 parent 584e49b commit fbba3f6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 18 deletions.
28 changes: 21 additions & 7 deletions src/react/For.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { useSelector } from './useSelector';

const autoMemoCache = new Map<FC<any>, FC<any>>();

type ForItemProps<T, TProps = {}> = {
item$: Observable<T>;
id?: string;
} & TProps;

export function For<T, TProps>({
each,
optimized: isOptimized,
Expand All @@ -16,10 +21,10 @@ export function For<T, TProps>({
}: {
each?: ObservableReadable<T[] | Record<any, T> | Map<any, T>>;
optimized?: boolean;
item?: FC<{ item: Observable<T>; id?: string } & TProps>;
item?: FC<ForItemProps<T, TProps>>;
itemProps?: TProps;
sortValues?: (A: T, B: T, AKey: string, BKey: string) => number;
children?: (value: Observable<T>) => ReactElement;
children?: (value: Observable<T>, id: string | undefined) => ReactElement;
}): ReactElement | null {
if (!each) return null;

Expand All @@ -30,10 +35,10 @@ export function For<T, TProps>({
// The child function gets wrapped in a memoized observer component
if (!item && children) {
// Update the ref so the generated component uses the latest function
const refChildren = useRef<(value: Observable<T>) => ReactElement>();
const refChildren = useRef<(value: Observable<T>, id: string | undefined) => ReactElement>();
refChildren.current = children;

item = useMemo(() => observer(({ item }) => refChildren.current!(item)), []);
item = useMemo(() => observer(({ item$, id }) => refChildren.current!(item$, id)), []);
} else {
// @ts-expect-error $$typeof is private
if (item.$$typeof !== Symbol.for('react.memo')) {
Expand Down Expand Up @@ -72,7 +77,14 @@ export function For<T, TProps>({
if (value[i]) {
const val = value[i];
const key = (isIdFieldFunction ? idField(val) : (val as Record<string, any>)[idField as string]) ?? i;
const props = { key, id: key, item: (each as Observable<any[]>)[i] };
const item$ = (each as Observable<any[]>)[i];
// TODOV3 Remove item
const props: ForItemProps<any> & { key: string; item: Observable<any> } = {
key,
id: key,
item$,
item: item$,
};

out.push(createElement(item as FC, itemProps ? Object.assign(props, itemProps) : props));
}
Expand All @@ -87,10 +99,12 @@ export function For<T, TProps>({
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (isMap ? value.get(key) : value[key]) {
const props = {
const item$ = isMap ? each!.get(key) : (each as ObservableObject<Record<string, any>>)[key];
const props: ForItemProps<any> & { key: string; item: Observable<any> } = {
key,
id: key,
item: isMap ? each!.get(key) : (each as ObservableObject<Record<string, any>>)[key],
item$,
item: item$,
};
out.push(createElement(item as FC, itemProps ? Object.assign(props, itemProps) : props));
}
Expand Down
22 changes: 11 additions & 11 deletions tests/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ describe('For', () => {
const obs = observable({
items: [{ id: 0, label: '0' }] as TestObject[],
});
function Item({ item }: { item: Observable<TestObject> }) {
const data = useSelector(item);
function Item({ item$ }: { item$: Observable<TestObject> }) {
const data = useSelector(item$);
return createElement('li', { id: data.id }, data.label);
}
function Test() {
Expand Down Expand Up @@ -357,8 +357,8 @@ describe('For', () => {
{ id: 'A', label: 'A' },
] as TestObject[],
});
function Item({ item }: { item: Observable<TestObject> }) {
const data = useSelector(item);
function Item({ item$ }: { item$: Observable<TestObject> }) {
const data = useSelector(item$);
return createElement('li', { id: data.id }, data.label);
}
function Test() {
Expand Down Expand Up @@ -401,9 +401,9 @@ describe('For', () => {
{ id: 'A', label: 'A' },
] as TestObject[],
});
function Item({ item }: { item: Observable<TestObject> }) {
const data = useSelector(item);
return createElement('li', { id: getObservableIndex(item) }, data.label);
function Item({ item$ }: { item$: Observable<TestObject> }) {
const data = useSelector(item$);
return createElement('li', { id: getObservableIndex(item$) }, data.label);
}
function Test() {
return createElement(
Expand All @@ -426,8 +426,8 @@ describe('For', () => {
['m1', { label: 'A', id: 'A' }],
]),
});
function Item({ item }: { item: Observable<TestObject> }) {
const data = useSelector(item);
function Item({ item$ }: { item$: Observable<TestObject> }) {
const data = useSelector(item$);
return createElement('li', { id: data.label }, data.label);
}
function Test() {
Expand All @@ -451,8 +451,8 @@ describe('For', () => {
['m1', { label: 'A', id: 'A' }],
]),
});
function Item({ item }: { item: Observable<TestObject> }) {
const data = useSelector(item);
function Item({ item$ }: { item$: Observable<TestObject> }) {
const data = useSelector(item$);
return createElement('li', { id: data.label }, data.label);
}
function Test() {
Expand Down

0 comments on commit fbba3f6

Please sign in to comment.