Skip to content

Commit c5df9d4

Browse files
committed
feat: use array index for unique keys, and add propIndex prop
1 parent 3861ba8 commit c5df9d4

3 files changed

Lines changed: 52 additions & 12 deletions

File tree

src/__helpers__/burger.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
import * as React from "react";
22

3-
export const Bun = ({ variant }: { variant: string }) => (
4-
<div>{`${variant} bun`}</div>
3+
export const Bun = ({
4+
variant,
5+
propIndex
6+
}: {
7+
variant: string;
8+
propIndex?: number;
9+
}) => (
10+
<div>
11+
<div>{propIndex && `Order: ${propIndex}`}</div>
12+
{`${variant} bun`}
13+
</div>
514
);
615

716
export const Patty = ({
817
id,
918
size,
10-
ingredient
19+
ingredient,
20+
propIndex
1121
}: {
1222
id: number;
1323
size: string;
1424
ingredient: React.ReactNode;
25+
propIndex?: number;
1526
}) => (
1627
<div id={`${id}`}>
28+
<div>{propIndex && `Order: ${propIndex}`}</div>
1729
{`${size} patty`}
1830
{ingredient}
1931
</div>
@@ -26,14 +38,17 @@ export const PattyIngredient = ({ variant }: { variant: string }) => (
2638
export const Burger = ({
2739
bun,
2840
cheese,
29-
children
41+
children,
42+
propIndex
3043
}: {
3144
bun: React.ReactNode;
3245
chain: string;
3346
cheese: boolean;
3447
children: React.ReactNode;
48+
propIndex?: number;
3549
}) => (
3650
<div>
51+
<div>{propIndex && `Order: ${propIndex}`}</div>
3752
<div>{bun}</div>
3853
<div>{cheese && "cheese"}</div>
3954
<div>{children}</div>

src/__tests__/__snapshots__/index.tsx.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
exports[`ReactFromJSON to render a flat entry with a components attribute 1`] = `
44
<div>
5+
<div />
56
<div>
67
<div>
8+
<div />
79
sesame bun
810
</div>
911
</div>
@@ -14,6 +16,9 @@ exports[`ReactFromJSON to render a flat entry with a components attribute 1`] =
1416
<div
1517
id="0"
1618
>
19+
<div>
20+
0
21+
</div>
1722
large patty
1823
<div>
1924
impossible
@@ -22,6 +27,9 @@ exports[`ReactFromJSON to render a flat entry with a components attribute 1`] =
2227
<div
2328
id="1"
2429
>
30+
<div>
31+
Order: 1
32+
</div>
2533
large patty
2634
<div>
2735
beef
@@ -30,6 +38,7 @@ exports[`ReactFromJSON to render a flat entry with a components attribute 1`] =
3038
</div>
3139
<div>
3240
<div>
41+
<div />
3342
sesame bun
3443
</div>
3544
</div>
@@ -38,8 +47,10 @@ exports[`ReactFromJSON to render a flat entry with a components attribute 1`] =
3847

3948
exports[`ReactFromJSON to render a recursive entry 1`] = `
4049
<div>
50+
<div />
4151
<div>
4252
<div>
53+
<div />
4354
sesame bun
4455
</div>
4556
</div>
@@ -50,6 +61,9 @@ exports[`ReactFromJSON to render a recursive entry 1`] = `
5061
<div
5162
id="undefined"
5263
>
64+
<div>
65+
0
66+
</div>
5367
large patty
5468
<div>
5569
impossible
@@ -58,6 +72,9 @@ exports[`ReactFromJSON to render a recursive entry 1`] = `
5872
<div
5973
id="undefined"
6074
>
75+
<div>
76+
Order: 1
77+
</div>
6178
large patty
6279
<div>
6380
beef
@@ -66,6 +83,7 @@ exports[`ReactFromJSON to render a recursive entry 1`] = `
6683
</div>
6784
<div>
6885
<div>
86+
<div />
6987
sesame bun
7088
</div>
7189
</div>

src/index.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface Component {
88
interface ComponentLookupProps {
99
componentType: string;
1010
componentIndex: number;
11+
propIndex?: number;
1112
}
1213

1314
export interface ComponentLookup {
@@ -44,7 +45,8 @@ class ReactFromJSON<
4445

4546
ComponentLookup = ({
4647
componentIndex,
47-
componentType
48+
componentType,
49+
propIndex
4850
}: ComponentLookupProps) => {
4951
const { components } = this.props;
5052

@@ -58,12 +60,13 @@ class ReactFromJSON<
5860
...component,
5961
props: {
6062
id: component.id || componentIndex, // Map id to component props if specified on root. Otherwise, use index.
63+
propIndex: propIndex,
6164
...component.props
6265
}
6366
});
6467
};
6568

66-
resolveProp = (prop: any): any => {
69+
resolveProp = (prop: any, index?: number): any => {
6770
if (prop === null) {
6871
return prop;
6972
} else if (Array.isArray(prop)) {
@@ -76,23 +79,25 @@ class ReactFromJSON<
7679
) {
7780
const component: Component = prop;
7881

79-
return this.renderComponent(component);
82+
return this.renderComponent(component, index);
8083
}
8184
}
8285

8386
return prop;
8487
};
8588

86-
getNextKey(type: string) {
89+
getNextKey(type: string, propIndex?: number) {
8790
this.counter[type] = this.counter[type] || 0;
88-
return `${type}_${this.counter[type]++}`;
91+
const propIndexKey =
92+
typeof propIndex !== "undefined" ? `_${propIndex}` : "";
93+
return `${type}_${this.counter[type]++}${propIndexKey}`;
8994
}
9095

91-
renderComponent(component: Component) {
96+
renderComponent(component: Component, propIndex?: number) {
9297
const { mapping } = this.props;
9398
const { type, props } = component;
9499
const resolvedProps = {};
95-
const key = this.getNextKey(type);
100+
const key = this.getNextKey(type, propIndex);
96101

97102
const propKeys = Object.keys(props);
98103

@@ -109,7 +114,9 @@ class ReactFromJSON<
109114
throw `Tried to render the "${type}" component, but it's not specified in your mapping.`;
110115
}
111116

112-
return <MappedComponent key={key} {...resolvedProps} />;
117+
return (
118+
<MappedComponent key={key} propIndex={propIndex} {...resolvedProps} />
119+
);
113120
}
114121

115122
render() {

0 commit comments

Comments
 (0)