Редактирование массива в React
Пусть у нас опять есть массив, каждый элемент которого выводится в абзаце:
function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);
const result = notes.map((note, index) => {
return <p key={index}>{note}</p>;
});
return <div>
{result}
</div>;
}
Сделаем возможность редактирования элементов нашего массива. Для этого под абзацами сделаем инпут. Пусть по клику на абзац его текст появляется в этом инпуте. Мы будем редактировать текст инпута и одновременно будет изменяться текст абзаца.
Давайте приступим к реализации.
Для начала давайте сделаем стейт editNum, хранящий номер редактируемого в данный момент элемента массива. Если же в данный момент у нас ничего не редактируется пусть этот editNum имеет значение null. Сделаем:
function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);
const [editNum, setEditNum] = useState(null);
...
}
Давайте теперь сделаем так, чтобы по клику на абзац в key записывался номер элемента массива, соответствующий этому абзацу:
function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);
const [editNum, setEditNum] = useState(null);
const result = notes.map((note, index) => {
return <p key={index} onClick={() => setEditNum(index)}>
{note}
</p>;
});
...
}
Теперь сделаем так, чтобы в инпуте выводился текст редактируемого элемента массива:
<input value={notes[editNum]} />
Это, однако, приведет к проблеме, если editNum равен null. В этом случае в value инпута попадет undefined, что не разрешено React. Для решения проблемы используем тернарный оператор:
<input value={editNum ? notes[editNum] : ''} />
Добавим теперь инпуту событие onChange:
<input value={editNum ? notes[editNum] : ''} onChange={changeItem} />
Реализуем обработчик этого события. В нем мы будем заменять редактируемый элемент массива на текст из инпута:
function changeItem(event) {
setNotes([...notes.slice(0, editNum), event.target.value, ...notes.slice(editNum + 1)]);
}
При этом получится, что при редактировании текста в инпуте, текст одновременно будет изменяться в абзаце!
Давайте соберем весь код вместе:
function App() {
const [notes, setNotes] = useState([1, 2, 3, 4, 5]);
const [editNum, setEditNum] = useState(null);
const result = notes.map((note, index) => {
return <p key={index} onClick={() => setEditNum(index)}>
{note}
</p>;
});
function changeItem(event) {
setNotes([...notes.slice(0, editNum), event.target.value, ...notes.slice(editNum + 1)]);
}
return <div>
{result}
<input value={editNum ? notes[editNum] : ''} onChange={changeItem} />
</div>;
}