Универсальная форма для массива объектов в React


Давайте теперь совместим добавление и редактирование массива объектов в одной форме. Пусть в конце каждого абзаца стоит кнопка для редактирования данных этого абзаца.

При нажатии на такую кнопку пусть наша форма переходит в режим редактирования. При завершении редактирования по нажатию на кнопку сохранения путь форма переходит в режим добавления.

Вот готовая реализация описанного:

function App() {
const [notes, setNotes] = useState(initNotes);
const [obj, setObj] = useState(getInitObj());
const [editId, setEditId] = useState(null);

const result = notes.map(note => {
return <p key={note.id}>
<span>{note.prop1}</span>,
<span>{note.prop2}</span>,
<span>{note.prop3}</span>

<button onClick={() => setEditId(note.id)}>edit</button>
</p>;
});

function getValue(prop) {
if (editId) {
return notes.reduce((res, note) => note.id === editId ? note[prop] : res, '');
} else {
return obj[prop];
}
}

function changeItem(prop, event) {
if (editId) {
setNotes(notes.map(note =>
note.id === editId ? {...note, [prop]: event.target.value} : note
));
} else {
setObj({...obj, [prop]: event.target.value});
}
}

function saveItem() {
if (editId) {
setEditId(null);
} else {
setNotes([...notes, obj]);
setObj(getInitObj());
}
}

return <div>
{result}

<br />

<input
value={getValue('prop1')}
onChange={event => changeItem('prop1', event)}
/>
<input
value={getValue('prop2')}
onChange={event => changeItem('prop2', event)}
/>
<input
value={getValue('prop3')}
onChange={event => changeItem('prop3', event)}
/>

<button onClick={saveItem}>save</button>
</div>;
}

function getInitObj() {
return {
id: id(),
prop1: '',
prop2: '',
prop3: ''
}
}