Обновление вложенного объекта n-уровня без мутаций в Redux - PullRequest
0 голосов
/ 28 октября 2019

У меня есть объект в следующем формате -

{
  operator: '~and~',
  displayOrder: '1',
  logicExpressionDtos: [
    {
      displayOrder: '1.1',
      expression: 'a ~eq~ b',
    },
  ],
  groups: [{
    operator: '',
    displayOrder: '1.2',
    logicExpressionDtos: [
    {
      displayOrder: '1.2.1',
      expression: 'a ~eq~ b',
    },
      {
      displayOrder: '1.2.2',
      expression: 'a ~eq~ b',
    },
  ],
    groups: []
  },
   {
    operator: '',
    displayOrder: '1.3',
    logicExpressionDtos: [
    {
      displayOrder: '1.3.1',
      expression: 'a ~eq~ b',
    },
      {
      displayOrder: '1.3.3',
      expression: 'a ~eq~ b',
    },
  ],
     groups: [{
    operator: '',
    displayOrder: '1.3.2',
    logicExpressionDtos: [
    {
      displayOrder: '1.3.2.1',
      expression: 'a ~eq~ b',
    },
      {
      displayOrder: '1.3.2.2',
      expression: 'a ~eq~ b',
    },
  ],
    groups: []
  }]
  }
 ]
}

Я отрисовал logicExpressionDtos в groups (и группы внутри группы). Как видно из приведенных примеров данных, группы могут быть вложены до уровня n. Теперь мне нужно вставить объект выражения в logicExpressionDtos в любой группе (на самом деле конечный пользователь может захотеть вставить в любую группу), поддерживая displayOrder. Я пытался справиться с этим с помощью следующего кода -

const iteratorFunctionForLogic = (logicObj, parentOrder) => {
  if (
    logicObj.groups &&
    logicObj.groups.filter((logic) => logic.displayOrder == parentOrder) &&
    logicObj.groups.filter((logic) => logic.displayOrder == parentOrder)[0]
  ) {
    const matchedLogic = logicObj.groups.filter(
      (e) => e.displayOrder == parentOrder
    );
    let logic = matchedLogic && matchedLogic.length ? matchedLogic[0] : {};
    const lastOrderId = [...logic.logicExpressionDtos, ...logic.groups]
      .map((e) => e.displayOrder.split('.').pop())
      .sort()
      .pop();

    const newOrder = `${parentOrder}.${parseInt(lastOrderId) + 1}`;
    logic.logicExpressionDtos = [
      ...logic.logicExpressionDtos,
      {
        displayOrder: newOrder,
        expression: 'x ~eq~ y',
      },
    ];
    logic.operator = logic.operator ? logic.operator : '~or';
  } else {
    logicObj.groups
      ? logicObj.groups.forEach((eachObj) =>
          iteratorFunctionForLogic(eachObj, parentOrder)
        )
      : null;
  }
};

const insertNewExpression = (logicObj, parentOrder) => {
  if (logicObj.displayOrder == parentOrder) {
    let logic = { ...logicObj };
    const lastOrderId = [...logic.logicExpressionDtos, ...logic.groups]
      .map((e) => e.displayOrder.split('.').pop())
      .sort()
      .pop();

    const newOrder = `${parentOrder}.${parseInt(lastOrderId) + 1}`;

    logic.logicExpressionDtos = [
      ...logic.logicExpressionDtos,
      {
        displayOrder: newOrder,
        expression: 'x ~eq~ y',
      },
    ];
    logic.operator = logic.operator ? logic.operator : '~or';
    return logic;
  } else {
    const newLogicObj = { ...logicObj };
    iteratorFunctionForLogic(newLogicObj, parentOrder);
    return newLogicObj;
  }
};

И, мой reducer.js

case ADD_NEW_EXPRESSION:
      const { parentOrder, conditionIndex } = action;
      const condition = { ...state.conditionArray[conditionIndex] };
      console.log(insertNewExpression(condition, parentOrder));
      return {
        ...state,
        conditionArray: state.conditionArray.map((condition, index) => {
          if (index != conditionIndex) return condition;
          return insertNewExpression(condition, parentOrder);
        }),
      };

, где parentOrder обозначает displayOrder группы, в которой пользовательхочет добавить новое выражение. Но redux выдает ошибку, говоря, что пытается изменить состояние. Может ли кто-нибудь помочь мне с лучшим подходом?

...