Я пытаюсь создать форму React / редактируемую таблицу, которая позволяет пользователю редактировать объект со следующей структурой:
{ID, name, year, number, categories: [ {ID, name, options: [ {ID, name} ] } ] }
Я пытался найти эффективный и чистый способ отображения данныхэтой формы, разрешить редактирование и отслеживать отредактированные данные в некотором родительском компоненте. Редактировать свойства уровня поверхности было довольно легко (и я считаю чистым). У меня был создатель обработчика событий, который взял имя параметра и менял этот параметр каждый раз, когда значение текстового поля изменялось.
const [Obj, setObject] = useState({ID: "", name: "", categories: []})
function changeEventHandlerCreator(name) {
return event => {
let edittedObject = Object.assign({}, Obj);
edittedObject[name] = event.target.value;
setObject(edittedObject);
};
}
Когда я пытался сделать аналогичный метод с вложеннымсвойства категорий / опций, это стало довольно грязно. Я сделал больше создателей обработчиков событий для категорий и опций:
function categoryChangeEventHandlerForCategory(category) {
return event => {
let edittedCategory = Object.assign({}, category);
edittedCategory.categoryName = event.target.value;
editCategory(edittedCategory, category);
};
}
function optionChangeEventHandlerForOptionInCategory(option, category) {
return event => {
let edittedOption = Object.assign({}, option, {
optionName: event.target.value
});
editOptionInCategory(edittedOption, option, category);
};
}
function editCategory(newCategory, oldCategory) {
let edittedCourse = Object.assign({}, course);
let edittedCategories = course.categories.map(category =>
category.categoryID !== oldCategory.categoryID ? category : newCategory
);
edittedCourse.categories = edittedCategories;
setCourse(edittedCourse);
}
function addOptionToCategory(category) {
let edittedCategory = Object.assign({}, category);
let option = {
optionID: nextOptionIndexForCategory(category),
optionName: "",
expanded: false
};
edittedCategory.options = [option, ...category.options];
edittedCategory.expanded = true;
editCategory(edittedCategory, category);
}
Я смог сделать небольшой ярлык здесь. Я знал, что собираюсь редактировать только одно свойство, имя категории / опции, поэтому мне не нужно было заботиться о редактировании нескольких свойств, как я сделал для основного объекта, что облегчило этот метод. Затем я передаю категорию / категорию и параметр создателям дескрипторов событий, чтобы убедиться, что эта функция специально изменяет эту категорию / параметр. Это делается путем отслеживания идентификатора. Создатели обработчиков событий для категорий используют идентификатор, чтобы знать, какая категория / опция редактируется. Это происходит в функции editCategory, где она отображает текущие категории в новый массив, но если идентификатор совпадает с переданной категорией, она возвращает новую категорию вместо старой. То же самое касается параметров редактирования.
Эти обработчики событий передаются компонентам редактора, как показано ниже:
<MainObjEdittor changeEventHandleCreator={changeEventHandlerCreator}/>
{Obj.categories.map(category =>
<CategoryEdittor categoryChangeEventHandlerForCategory(category)/>
{category.options.map(option =>
<OptionEdittor optionChangeEventHandlerForOptionInCategory(option, category)/>
)}
)}
Мой вопрос заключается в том, является ли это лучшим способом сделать это? Не похоже, что это так. Моя цель - просто иметь возможность редактировать любое свойство любого объекта в основном объекте. Кроме того, если я теперь понимаю, что мне нужно будет редактировать больше, чем просто свойство name категорий и опций, чтобы этот метод не работал (или просто стал бы более грязным). Что было бы хорошим методом для