Skip to content

Commit ecf0d0e

Browse files
fix: stabilize React keys in MultiPairInputModal demo (#23)
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 81afeaa commit ecf0d0e

2 files changed

Lines changed: 26 additions & 24 deletions

File tree

examples/demo/src/components/modals/MultiPairInputModal.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { MdClose } from 'react-icons/md';
44

55
import ModalShell from './ModalShell';
66

7-
type Row = { key: string; value: string };
7+
type Row = { id: number; key: string; value: string };
8+
9+
let nextRowId = 0;
10+
const createRow = (): Row => ({ id: nextRowId++, key: '', value: '' });
811

912
interface MultiPairInputModalProps {
1013
open: boolean;
@@ -23,11 +26,11 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
2326
onClose,
2427
onSubmit,
2528
}) => {
26-
const [rows, setRows] = useState<Row[]>([{ key: '', value: '' }]);
29+
const [rows, setRows] = useState<Row[]>(() => [createRow()]);
2730

2831
useEffect(() => {
2932
if (open) {
30-
setRows([{ key: '', value: '' }]);
33+
setRows([createRow()]);
3134
}
3235
}, [open]);
3336

@@ -57,14 +60,14 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
5760
>
5861
<h3>{title}</h3>
5962
{rows.map((row, index) => (
60-
<div key={`row-${index}`}>
63+
<div key={row.id}>
6164
<div className="inline-fields row-with-remove">
6265
<input
6366
value={row.key}
6467
onChange={(event) =>
6568
setRows((prev) =>
66-
prev.map((entry, entryIndex) =>
67-
entryIndex === index ? { ...entry, key: event.target.value } : entry,
69+
prev.map((entry) =>
70+
entry.id === row.id ? { ...entry, key: event.target.value } : entry,
6871
),
6972
)
7073
}
@@ -75,8 +78,8 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
7578
value={row.value}
7679
onChange={(event) =>
7780
setRows((prev) =>
78-
prev.map((entry, entryIndex) =>
79-
entryIndex === index ? { ...entry, value: event.target.value } : entry,
81+
prev.map((entry) =>
82+
entry.id === row.id ? { ...entry, value: event.target.value } : entry,
8083
),
8184
)
8285
}
@@ -87,9 +90,7 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
8790
<button
8891
type="button"
8992
className="delete-btn"
90-
onClick={() =>
91-
setRows((prev) => prev.filter((_, entryIndex) => entryIndex !== index))
92-
}
93+
onClick={() => setRows((prev) => prev.filter((entry) => entry.id !== row.id))}
9394
>
9495
<MdClose />
9596
</button>
@@ -101,7 +102,7 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
101102
<button
102103
type="button"
103104
className="text-btn text-btn-center"
104-
onClick={() => setRows((prev) => [...prev, { key: '', value: '' }])}
105+
onClick={() => setRows((prev) => [...prev, createRow()])}
105106
data-testid="multipair_add_row_button"
106107
>
107108
+ Add Row

examples/demo_pods/src/components/modals/MultiPairInputModal.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { MdClose } from 'react-icons/md';
44

55
import ModalShell from './ModalShell';
66

7-
type Row = { key: string; value: string };
7+
type Row = { id: number; key: string; value: string };
8+
9+
let nextRowId = 0;
10+
const createRow = (): Row => ({ id: nextRowId++, key: '', value: '' });
811

912
interface MultiPairInputModalProps {
1013
open: boolean;
@@ -23,11 +26,11 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
2326
onClose,
2427
onSubmit,
2528
}) => {
26-
const [rows, setRows] = useState<Row[]>([{ key: '', value: '' }]);
29+
const [rows, setRows] = useState<Row[]>(() => [createRow()]);
2730

2831
useEffect(() => {
2932
if (open) {
30-
setRows([{ key: '', value: '' }]);
33+
setRows([createRow()]);
3134
}
3235
}, [open]);
3336

@@ -57,14 +60,14 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
5760
>
5861
<h3>{title}</h3>
5962
{rows.map((row, index) => (
60-
<div key={`row-${index}`}>
63+
<div key={row.id}>
6164
<div className="inline-fields row-with-remove">
6265
<input
6366
value={row.key}
6467
onChange={(event) =>
6568
setRows((prev) =>
66-
prev.map((entry, entryIndex) =>
67-
entryIndex === index ? { ...entry, key: event.target.value } : entry,
69+
prev.map((entry) =>
70+
entry.id === row.id ? { ...entry, key: event.target.value } : entry,
6871
),
6972
)
7073
}
@@ -75,8 +78,8 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
7578
value={row.value}
7679
onChange={(event) =>
7780
setRows((prev) =>
78-
prev.map((entry, entryIndex) =>
79-
entryIndex === index ? { ...entry, value: event.target.value } : entry,
81+
prev.map((entry) =>
82+
entry.id === row.id ? { ...entry, value: event.target.value } : entry,
8083
),
8184
)
8285
}
@@ -87,9 +90,7 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
8790
<button
8891
type="button"
8992
className="delete-btn"
90-
onClick={() =>
91-
setRows((prev) => prev.filter((_, entryIndex) => entryIndex !== index))
92-
}
93+
onClick={() => setRows((prev) => prev.filter((entry) => entry.id !== row.id))}
9394
>
9495
<MdClose />
9596
</button>
@@ -101,7 +102,7 @@ const MultiPairInputModal: FC<MultiPairInputModalProps> = ({
101102
<button
102103
type="button"
103104
className="text-btn text-btn-center"
104-
onClick={() => setRows((prev) => [...prev, { key: '', value: '' }])}
105+
onClick={() => setRows((prev) => [...prev, createRow()])}
105106
data-testid="multipair_add_row_button"
106107
>
107108
+ Add Row

0 commit comments

Comments
 (0)