Skip to content

Commit 34eb478

Browse files
authored
Fix keys warning due to intersperse (#1912)
* stick keys on the sep and conj in intersperse * go buck wild on the test, why not
1 parent 4d69308 commit 34eb478

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed
Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8+
import { type ReactElement } from 'react'
89
import { expect, test } from 'vitest'
910

1011
import { groupBy, intersperse, lowestBy, sortBy, sumBy } from './array'
@@ -68,12 +69,31 @@ test('sumBy', () => {
6869
})
6970

7071
test('intersperse', () => {
71-
expect(intersperse([], 'x')).toEqual([])
72-
expect(intersperse(['a'], 'x')).toEqual(['a'])
72+
expect(intersperse([], <>,</>)).toEqual([])
7373

74-
expect(intersperse(['a', 'b'], ',')).toEqual(['a', ',', 'b'])
75-
expect(intersperse(['a', 'b'], ',', 'or')).toEqual(['a', 'or', 'b'])
74+
const a = <span key="a">a</span>
75+
const b = <span key="b">b</span>
76+
const c = <span key="c">c</span>
77+
const comma = <>,</>
78+
const or = <>or</>
7679

77-
expect(intersperse(['a', 'b', 'c'], ',')).toEqual(['a', ',', 'b', ',', 'c'])
78-
expect(intersperse(['a', 'b', 'c'], ',', 'or')).toEqual(['a', ',', 'b', ',', 'or', 'c'])
80+
const getText = (el: ReactElement) => el.props.children
81+
const getKey = (el: ReactElement) => el.key
82+
83+
expect(intersperse([a], comma).map(getText)).toEqual(['a'])
84+
expect(intersperse([a], comma).map(getKey)).toEqual(['a'])
85+
86+
expect(intersperse([a, b], comma).map(getText)).toEqual(['a', ',', 'b'])
87+
expect(intersperse([a, b], comma).map(getKey)).toEqual(['a', 'sep-1', 'b'])
88+
89+
expect(intersperse([a, b], comma, or).map(getText)).toEqual(['a', 'or', 'b'])
90+
expect(intersperse([a, b], comma, or).map(getKey)).toEqual(['a', 'conj', 'b'])
91+
92+
let result = intersperse([a, b, c], comma)
93+
expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'c'])
94+
expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'c'])
95+
96+
result = intersperse([a, b, c], comma, or)
97+
expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'or', 'c'])
98+
expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'conj', 'c'])
7999
})

libs/util/array.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* Copyright Oxide Computer Company
77
*/
88

9+
import { cloneElement, type ReactElement } from 'react'
10+
911
/* eslint-disable @typescript-eslint/no-explicit-any */
1012
const identity = (x: any) => x
1113

@@ -80,12 +82,23 @@ export function sumBy<T>(items: T[], fn: (item: T) => number): number {
8082
/**
8183
* If a conjunction is included, use that instead of `sep` when there are two items.
8284
*/
83-
export function intersperse<T>(items: T[], sep: T, conj?: T): T[] {
85+
export function intersperse(
86+
items: ReactElement[],
87+
sep: ReactElement,
88+
conj?: ReactElement
89+
): ReactElement[] {
8490
if (items.length <= 1) return items
85-
if (conj && items.length === 2) return [items[0], conj, items[1]]
91+
if (conj && items.length === 2) {
92+
const conj0 = cloneElement(conj, { key: `conj` })
93+
return [items[0], conj0, items[1]]
94+
}
8695
return items.flatMap((item, i) => {
8796
if (i === 0) return [item]
88-
if (conj && i === items.length - 1) return [sep, conj, item]
89-
return [sep, item]
97+
const sep0 = cloneElement(sep, { key: `sep-${i}` })
98+
if (conj && i === items.length - 1) {
99+
const conj0 = cloneElement(conj, { key: `conj` })
100+
return [sep0, conj0, item]
101+
}
102+
return [sep0, item]
90103
})
91104
}

0 commit comments

Comments
 (0)