Обновить глубоко вложенное свойство объекта в списке immutableJS - PullRequest
0 голосов
/ 28 августа 2018

У меня следующая иерархия неизменного списка:

fromJS({
departments: [{
    departmentName: 'PHP',
    employees: [{
        employeeId: 1000,
        employeeName: 'Manish',
        projects: [{
            projectId: 200,
            projectName: 'ABC'
        },
        {
            projectId: 300,
            projectName: 'DEF'
        }]
    }]
}]
})

В этом списке я хочу обновить имя проекта с идентификатором проекта 200 . Хотя я могу обновить простой одноуровневый массив объектов, найдя их индексы, но я понятия не имею, как начать с этого в immutableJS.

Ответы [ 3 ]

0 голосов
/ 29 августа 2018

Я считаю, что идиоматический способ сделать это с помощью 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'));
0 голосов
/ 18 сентября 2018

Я рекомендую вам либо не использовать immutable.js для таких сложных структур данных, либо реорганизовать структуры в простые коллекции. В противном случае не только вы будете страдать от ада технического обслуживания, но производительность будет в сотни раз хуже (но все же вы можете не заметить этого, в зависимости от вашего приложения).

0 голосов
/ 28 августа 2018

У меня было нечто подобное давным-давно ... Я использовал функцию 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}
                                }
                            }))
                        }
                    }))
                }
            }))
        }
    }
...