Пусть у нас есть массив:
const initNotes = [
'note1',
'note2',
'note3',
];
Давайте выведем этот массив в виде списка
ul
. Затем сделаем так, чтобы по клику
на любую лишку в ней появлялся инпут для
редактирования ее текста.
Шаг 1
Для решения задачи нам придется модифицировать наш массив так, чтобы для каждого элемента было указано, в каком режиме он находится: в показе или в редактировании.
Сделаем это:
const initNotes = [
{text: 'note1', isEdit: false},
{text: 'note2', isEdit: false},
{text: 'note3', isEdit: false},
];
Шаг 2
Выведем наш массив виде списка ul:
function App() {
const [notes, setNotes] = useState(initNotes);
const result = notes.map((note, index) => {
return <li key={index}>{note.text}</li>;
});
return <ul>
{result}
</ul>;
}
Шаг 3
Сделаем так, чтобы в режиме показа показывался
span
с текстом, а в режиме редактирования
- инпут:
const result = notes.map((note, index) => {
let elem;
if (!note.isEdit) {
elem = <span>{note.text}</span>;
} else {
elem = <input value={note.text} />;
}
return <li key={index}>{elem}</li>;
});
return <ul>
{result}
</ul>;
Шаг 4
По клику на span
будем включать режим
редактирования для данной лишки:
const result = notes.map((note, index) => {
let elem;
if (!note.isEdit) {
elem = <span onClick={() => startEdit(index)}>
{note.text}
</span>;
} else {
elem = <input value={note.text} />;
}
return <li key={index}>{elem}</li>;
});
Реализуем функцию startEdit
:
function startEdit(index) {
const copy = Object.assign([], notes);
copy[index].isEdit = true;
setNotes(copy);
}
Шаг 5
Сделаем так, чтобы в инпут можно было вводить текст и при этом изменялся соответствующий элемент массива:
const result = notes.map((note, index) => {
let elem;
if (!note.isEdit) {
elem = <span onClick={() => startEdit(index)}>
{note.text}
</span>;
} else {
elem = <input
value={note.text}
onChange={event => changeNote(index, event)}
/>;
}
return <li key={index}>{elem}</li>;
});
Реализуем функцию changeNote
:
function changeNote(index, event) {
const copy = Object.assign([], notes);
copy[index].text = event.target.value;
setNotes(copy);
}
Шаг 6
По потери фокуса будем отключать режим редактирования лишки:
const result = notes.map((note, index) => {
let elem;
if (!note.isEdit) {
elem = <span onClick={() => startEdit(index)}>
{note.text}
</span>;
} else {
elem = <input
value={note.text}
onChange={event => changeNote(index, event)}
onBlur={() => endEdit(index)}
/>;
}
return <li key={index}>{elem}</li>;
});
Реализуем функцию endEdit
:
function endEdit(index) {
const copy = Object.assign([], notes);
copy[index].isEdit = false;
setNotes(copy);
}
Шаг 7
Соберем все вместе и получим решение нашей задачи:
function App() {
const [notes, setNotes] = useState(initNotes);
function startEdit(index) {
const copy = Object.assign([], notes);
copy[index].isEdit = true;
setNotes(copy);
}
function endEdit(index) {
const copy = Object.assign([], notes);
copy[index].isEdit = false;
setNotes(copy);
}
function changeNote(index, event) {
const copy = Object.assign([], notes);
copy[index].text = event.target.value;
setNotes(copy);
}
const result = notes.map((note, index) => {
let elem;
if (!note.isEdit) {
elem = <span onClick={() => startEdit(index)}>
{note.text}
</span>;
} else {
elem = <input
value={note.text}
onChange={event => changeNote(index, event)}
onBlur={() => endEdit(index)}
/>;
}
return <li key={index}>{elem}</li>;
});
return <ul>
{result}
</ul>;
}
Практические задачи
Дан массив. Выведите его в виде списка ul
.
В конце каждой li
сделайте кнопку
для редактирования. Пусть по первому нажатию
на эту кнопку в тексте li
появляется
инпут для редактирования, а по второму нажатию
- появляется измененный текст.