adobe / adobe/react-spectrum

Setting Picker Item key prop causes keys to be coerced to a string regardless of the actual type

Open
#6,103 18 comments 0 reactions 0 assignees View on GitHub
enhancement has workaround
Dominant language
TypeScript
Stars
15.9k
Forks
1.6k
Avg merge
3d 9m
Merged PRs (30d)
59

Description

### Provide a general summary of the issue here

The Picker component supports items with numeric id / key props.

### Item.key unset
If the `Item.key` prop is not explicitly set, keys get derived from the `id` or `key` props on the items array.

e.g.

```jsx
function Example() {
let items = [
{ id: 1, name: 'Aardvark' },
{ id: 2, name: 'Cat' },
{ id: 3, name: 'Dog' }, ];

let [animalId, setAnimalId] = React.useState(null);

return (
<>

{ /* Item.key not explicitly set */
(item) => {item.name}
}

Animal id type: {typeof animalId}



);
}
```

The `onSelectionChange` handler will pass a numeric key to `setAnimalId` (consistent with the items data) and `value` + `defaultValue` will work with values of type `number`.

### Item.key explicitly set
If the `Item.key` prop is explicitly set e.g.

```jsx
{item.name}}
```

The `onSelectionChange` will pass a string id to `setAnimalId`, and the `value` + `defaultValue` props will require values of type `string` in order to work.

### 🤔 Expected Behavior?

I would expect in the case of setting `Item.key` prop explicitly:
* `onSelectionChange` should pass the actual value (not the stringified version) of the original id / key
* `value`, and `defaultValue` should be able to match the id / key prop on the items instead of requiring them to be string values

### 😯 Current Behavior

When `Item.key` prop is explicitly set
* `onSelectionChange` passes a stringified value of the original id / key
* `value`, and `defaultValue` don't match the items id / key prop unless they are stringified

### 💁 Possible Solution

_No response_

### 🔦 Context

We have a wrapper component that needs to explicitly set the `Item.key` prop based on properties on the `items`. In cases where these props are `numeric` or `boolean` types, this forces the input `value` + `onSelectedValue` change handlers to work with strings which doesn't match the original data.

### 🖥️ Steps to Reproduce

[https://codesandbox.io/p/sandbox/modern-shadow-znqpwf](https://codesandbox.io/p/sandbox/modern-shadow-znqpwf?file=%2Fsrc%2FApp.js%3A22%2C25&layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clu8m4b1r00063b6qt0em6lmr%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clu8m4b1r00023b6qa3ncq69w%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clu8m4b1r00033b6qnvq8g9lk%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clu8m4b1r00053b6q8rg0tzb0%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clu8m4b1r00023b6qa3ncq69w%2522%253A%257B%2522id%2522%253A%2522clu8m4b1r00023b6qa3ncq69w%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clu8m4rnj00513b6q8rkyrj65%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A22%252C%2522startColumn%2522%253A25%252C%2522endLineNumber%2522%253A22%252C%2522endColumn%2522%253A25%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252FApp.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clu8m4rnj00513b6q8rkyrj65%2522%257D%252C%2522clu8m4b1r00053b6q8rg0tzb0%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clu8m4b1r00043b6qt6yqaeqs%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clu8m4b1r00053b6q8rg0tzb0%2522%252C%2522activeTabId%2522%253A%2522clu8m4b1r00043b6qt6yqaeqs%2522%257D%252C%2522clu8m4b1r00033b6qnvq8g9lk%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clu8m4b1r00033b6qnvq8g9lk%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D)

### Version

3.34.1

### What browsers are you seeing the problem on?

Chrome

### If other, please specify.

_No response_

### What operating system are you using?

MacOS

### 🧢 Your Company/Team

_No response_

### 🕷 Tracking Issue

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with the Picker component and the linked CodeSandbox reproduction, comparing items whose ids are numeric or boolean with and without an explicit Item.key. Done means explicit keys preserve their original value type so onSelectionChange, value, and defaultValue work without stringifying those values; verify against the reported version 3.34.1 behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.