Пусть у нас опять есть массив, каждый элемент которого выводится в абзаце:
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
.
Модифицируйте предыдущую задачу так, чтобы при потере фокуса в инпуте его текст очищался.