Редактирование массива в 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>; }

Дан массив:

const notes = ['a', 'b', 'c', 'd', 'e'];

Выведите элементы этого массива в виде списка ul. Под списком реализуйте инпут для редактирования пунктов списка. Пусть в конце каждой li стоит кнопка, по нажатию на которую будет начинаться редактирование этой li.

Модифицируйте предыдущую задачу так, чтобы при потере фокуса в инпуте его текст очищался.