Условно обновить часть состояния с помощью useState

Я пытаюсь обновить свое состояние, чтобы включить новый информационный объект , если имя этого нового информационного объекта совпадает с именем в состоянии. Например....

при появлении новой информации:

{
serviceName:
    name: A
    properties:{
    cost: 300
    service:"Good"
    }
}


совпадает с названием существующего состояния:

{
serviceName:
    name: A
    properties:{
    cost: 600
    service:"Bad"
    }
}

Цель состоит в том, чтобы затем я мог объединить только свойства, что привело бы к:

{
serviceName:
    name: A
    properties:{
    cost: [300,600]
    service:["Good", "Bad"]
    }
}

Ближайшее, что я получил, работает с первым совпадением, но последующие совпадения приводят к массиву массивов, например (три элемента совпадают, поэтому должен был быть массив с 3 элементами по стоимости и обслуживанию):

{
    "name": "State",
    "value": [
      {
        "serviceName": {
          "name": "Informational Website - subscription",
          "properties": {
            "service": [
              [
                "Mobile-ready, Responsive Design",
                "Blog Articles"
              ],
              "Collect visitor information (email / phone)"
            ],
            "cost": [
              [
                "300",
                "500"
              ],
              "500"
            ]
          }
        }
      }
    ],
    "subHooks": []
  },

Я добился этого с помощью следующего кода:

  const [informationalService, setInformationalService] = useState([]);

  const handleChecking = (e, item) => {
    const { name } = e.target;
    if (informationalService.length > 0) {
      const selectedName = informationalService.filter(
        selection => selection.serviceName.name === name
      );

      const selectedNamePropertiesCost = selectedName.map(
        prop => prop.serviceName.properties.cost
      );

      const selectedNamePropertiesService = selectedName.map(
        prop => prop.serviceName.properties.service
      );

      const notSelectedName = informationalService.filter(
        selection => selection.serviceName.name !== name
      );
      const serviceChecked = selectedName.filter(
        selected => selected.serviceName.properties.service !== item.service
      );

      setInformationalService([
        ...notSelectedName,
        {
          serviceName: {
            name,
            properties: {
              service: [...selectedNamePropertiesService, item.service],
              cost: [...selectedNamePropertiesCost, item.cost]
            }
          }
        }
      ]);
    } else {
      setInformationalService([
        {
          serviceName: {
            name,
            properties: {
              service: item.service,
              cost: item.cost
            }
          }
        }
      ]);
    }
  };


person realhat    schedule 21.02.2020    source источник
comment
Я рекомендую для значений service и cost использовать согласованные типы данных. В вашем случае начальные значения должны быть массивом с одним элементом в них. Когда вам нужно его изменить, вы можете помещать новые элементы в массивы.   -  person Hoyen    schedule 21.02.2020
comment
@Hoyen, спасибо. Не могли бы вы подробнее рассказать о том, что вы подразумеваете под моими значениями, используя согласованные типы данных? Вы имеете в виду в моем примере стоимость: [300], обслуживание: [Хорошо]?   -  person realhat    schedule 22.02.2020


Ответы (1)


Я проигнорирую часть после вашей цели и сделаю следующее:

let data = {
serviceName: {
    name: "A",
    properties:{
    cost: 300,
    service:"Good"
    }
}
let olddata = {
serviceName: {
    name: "A",
    properties:{
    cost: 600,
    service:"Bad"
    }
};
let newprops = {},
 dataprops = data.serviceName.properties,
 olddataprops = olddata.serviceName.properties;

for (let prop in dataprops) {
  if (olddataprops[prop]) {
    newprops[prop] = [dataprops[prop], olddataprops[prop]];
  } else {
    newprops[prop] = dataprops[prop];
  }
}
person Learn for Fun    schedule 21.02.2020