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