Skip to content

Commit

Permalink
Fix keys warning due to intersperse (#1912)
Browse files Browse the repository at this point in the history
* stick keys on the sep and conj in intersperse

* go buck wild on the test, why not
  • Loading branch information
david-crespo authored Jan 26, 2024
1 parent 4d69308 commit 34eb478
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
32 changes: 26 additions & 6 deletions libs/util/array.spec.ts → libs/util/array.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*
* Copyright Oxide Computer Company
*/
import { type ReactElement } from 'react'
import { expect, test } from 'vitest'

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

test('intersperse', () => {
expect(intersperse([], 'x')).toEqual([])
expect(intersperse(['a'], 'x')).toEqual(['a'])
expect(intersperse([], <>,</>)).toEqual([])

expect(intersperse(['a', 'b'], ',')).toEqual(['a', ',', 'b'])
expect(intersperse(['a', 'b'], ',', 'or')).toEqual(['a', 'or', 'b'])
const a = <span key="a">a</span>
const b = <span key="b">b</span>
const c = <span key="c">c</span>
const comma = <>,</>
const or = <>or</>

expect(intersperse(['a', 'b', 'c'], ',')).toEqual(['a', ',', 'b', ',', 'c'])
expect(intersperse(['a', 'b', 'c'], ',', 'or')).toEqual(['a', ',', 'b', ',', 'or', 'c'])
const getText = (el: ReactElement) => el.props.children
const getKey = (el: ReactElement) => el.key

expect(intersperse([a], comma).map(getText)).toEqual(['a'])
expect(intersperse([a], comma).map(getKey)).toEqual(['a'])

expect(intersperse([a, b], comma).map(getText)).toEqual(['a', ',', 'b'])
expect(intersperse([a, b], comma).map(getKey)).toEqual(['a', 'sep-1', 'b'])

expect(intersperse([a, b], comma, or).map(getText)).toEqual(['a', 'or', 'b'])
expect(intersperse([a, b], comma, or).map(getKey)).toEqual(['a', 'conj', 'b'])

let result = intersperse([a, b, c], comma)
expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'c'])
expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'c'])

result = intersperse([a, b, c], comma, or)
expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'or', 'c'])
expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'conj', 'c'])
})
21 changes: 17 additions & 4 deletions libs/util/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Copyright Oxide Computer Company
*/

import { cloneElement, type ReactElement } from 'react'

/* eslint-disable @typescript-eslint/no-explicit-any */
const identity = (x: any) => x

Expand Down Expand Up @@ -80,12 +82,23 @@ export function sumBy<T>(items: T[], fn: (item: T) => number): number {
/**
* If a conjunction is included, use that instead of `sep` when there are two items.
*/
export function intersperse<T>(items: T[], sep: T, conj?: T): T[] {
export function intersperse(
items: ReactElement[],
sep: ReactElement,
conj?: ReactElement
): ReactElement[] {
if (items.length <= 1) return items
if (conj && items.length === 2) return [items[0], conj, items[1]]
if (conj && items.length === 2) {
const conj0 = cloneElement(conj, { key: `conj` })
return [items[0], conj0, items[1]]
}
return items.flatMap((item, i) => {
if (i === 0) return [item]
if (conj && i === items.length - 1) return [sep, conj, item]
return [sep, item]
const sep0 = cloneElement(sep, { key: `sep-${i}` })
if (conj && i === items.length - 1) {
const conj0 = cloneElement(conj, { key: `conj` })
return [sep0, conj0, item]
}
return [sep0, item]
})
}

0 comments on commit 34eb478

Please sign in to comment.