Удалили строку в React, а её заметка осталась у другого пользователя
Представим: в списке два человека, у каждого поле для заметки. Вводим «Позвонить вечером» рядом с Анной, удаляем Анну — и видим ту же заметку у Бориса.
Данные людей не перепутаны. Проблема в том, как React сопоставляет строки между рендерами.
Вот компонент, в котором ошибку можно воспроизвести:
import { useState } from "react"; function Row({ person }) { const [note, setNote] = useState(""); return ( <label> {person.name} <input value={note} onChange={event => setNote(event.target.value)} /> </label> ); } export default function App() { const [people, setPeople] = useState([ { id: "anna", name: "Анна" }, { id: "boris", name: "Борис" } ]); return ( <div> <button onClick={() => setPeople(p => p.slice(1))}> Удалить первого </button> {people.map((person, index) => ( <Row key={index} person={person} /> ))} </div> ); }
До удаления ключ 0 принадлежит строке Анны. После удаления ключ 0 получает строка Бориса. Для React это тот же компонент на прежнем месте с тем же ключом, поэтому его состояние note сохраняется. При этом person уже содержит Бориса.
Для этого списка исправление выглядит так:
{people.map(person => ( <Row key={person.id} person={person} /> ))}
Теперь у Бориса остаётся собственный ключ boris. При удалении Анны её компонент размонтируется, а состояние строки Бориса сохранится.
Ключ должен быть стабильным для одной записи и уникальным среди соседних элементов. Случайный ключ на каждом рендере тоже создаёт проблему: React будет пересоздавать компоненты, сбрасывая их состояние. Индекс не приводит к ошибке в любом списке, но для списка с удалением, вставкой или перестановкой записей он не сохраняет связь состояния с записью.
Проверить исправление можно в обе стороны: заметка Анны исчезает вместе с Анной, а заметка Бориса остаётся у Бориса после удаления предыдущей строки. Затем стоит повторить проверку с сортировкой списка.
Есть и отдельное ограничение: правильный key не хранит черновик после размонтирования. Если фильтр скрывает Бориса, удаляя его Row из дерева, при возвращении строки локальная заметка начнётся заново. Для сохранения таких черновиков состояние нужно поднять выше и хранить по person.id.
Если при сортировке или удалении элементы будто обмениваются введёнными значениями, стоит проверить ключи до того, как искать ошибку в обработчиках формы.













