Обновить глубоко вложенное свойство объекта в списке immutableJS
У меня есть следующая иерархия неизменного списка:
fromJS({
departments: [{
departmentName: 'PHP',
employees: [{
employeeId: 1000,
employeeName: 'Manish',
projects: [{
projectId: 200,
projectName: 'ABC'
},
{
projectId: 300,
projectName: 'DEF'
}]
}]
}]
})
В этом списке я хочу обновить имя проекта с идентификатором проекта 200. Хотя я могу обновить простой одноуровневый массив объектов, найдя их индексы, но я понятия не имею, как начать с этого в immutableJS.
3 ответа
Я рекомендую либо не использовать immutable.js для таких сложных структур данных, либо реорганизовать структуры в простые коллекции. В противном случае не только вы будете страдать от ада технического обслуживания, но производительность будет в сотни раз хуже (но все же вы можете не заметить этого, в зависимости от вашего приложения).
У меня было нечто подобное давным-давно... Я использовал функцию flatMap. В конце концов я изменил свою структуру состояний, так как поддержание этого кода было кошмаром.
updateProduct = (id, newName, data) => {
return {
departments: Immutable.flatMap(data.departments, (department => {
return {
...department,
employees: Immutable.flatMap(department.employees, (employee => {
return {
...employee,
projects: Immutable.flatMap(employee.projects, (project => {
if (project.projectId == id) {
return {
...project,
projectName: newName
}
}
else {
return {...project}
}
}))
}
}))
}
}))
}
}
Я считаю, что идиоматический способ сделать это с Immutable будет использовать много .map
а также .update
звонки:
const state = fromJS(/*...*/);
const newState = state.update('departments',
departments => departments.map(
department => department.update('employees',
employees => employees.map(
employee => employee.update('projects',
projects => projects.map(
project => project.get('projectId') === 200 ?
project.set('projectName', 'NEW_PROJECT_NAME') :
project
))))));
const state = Immutable.fromJS({
departments: [{
departmentName: 'PHP',
employees: [{
employeeId: 1000,
employeeName: 'Manish',
projects: [{
projectId: 200,
projectName: 'ABC'
},
{
projectId: 300,
projectName: 'DEF'
}
]
}]
}]
})
const newState = state.update('departments',
departments => departments.map(
department => department.update('employees',
employees => employees.map(
employee => employee.update('projects',
projects => projects.map(
project => project.get('projectId') === 200 ?
project.set('projectName', 'NEW_PROJECT_NAME') :
project
))))));
console.log(newState);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>
Работа с глубоко вложенными данными раздражает. Я думаю, что вы могли бы сделать свою жизнь намного проще, если бы вы немного упростили свои структуры данных. Возьмите эту структуру, например:
const state = fromJS({
departments: [{
employeeIds: [ 1000 ]
}],
employees: {
1000: {
employeeId: 1000,
employeeName: 'Manish',
projectIds: [ 200, 300 ]
}
},
projects: {
200: {
projectId: 200,
projectName: 'ABC'
},
300: {
projectId: 300,
projectName: 'DEF'
}
}
});
С такой структурой, ответ на ваш оригинальный вопрос будет так же просто, как один updateIn
:
const newState = state.updateId(['projects', 200],
project => project.set('projectName', 'NEW_PROJECT_NAME'));