嵌套对象在 React 中发生变异

Nested Object mutates in React

我几乎急需帮助。我是一名机械工程师,我正在为我的工作做一种计算器。我有一个问题,我已经花了几周时间。我似乎无法解决它。

为了不让您厌烦冗长的代码,我会尽量概括它。

代码示例

父对象

import {childObject} from "./childObject"

// in my code "childObject" are actually different from each other
const object1 = Object.assign({}, childObject);
const object2 = Object.assign({}, childObject);
const object3 = Object.assign({}, childObject);
const object4 = Object.assign({}, childObject);
const object5 = Object.assign({}, childObject);
const object6 = Object.assign({}, childObject);

const exampleObject = {
 name: "foo",
 otherInfo: "bar",
 nestedObject:{
  standardType: [object1, object2, object3],
  specialType: [object4, object5, object6]
 },
 sumfunc(){}
}

子对象

export const childObject = {
 name: "I'm losing my mind",
 value: "" //<-- this will change
 otherInfo: "please help me",
 sumfunc(){}
}

解释

我正在做的是:

  1. 包含所有类型父对象的搜索栏。
  2. 允许用户select一个或多个相同或不同的父对象。
  3. 将复制的 selection 存储在 redux 存储中。
  4. 显示 selection,每个 parentObject 作为一个表单。 [见图]
  5. 在表单中输入时,嵌套对象的值会改变

现在...问题是当我打开搜索栏和 select 相同的 parentObject,从而复制它时,它的所有值都发生了变化。如上图所示。

我尝试了什么

我试过的所有方法都没有阻止突变。 deepClone 方法停止了突变,但在 return 中,对象中的函数停止工作(也许我需要以某种方式绑定它?)

更多内容

更新nestedObject值的代码

const inputsHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    const formCopy = Object.assign({}, formEQ);
    const inputFieldName = e.target.name;

    // if anything other than a empty, number or decimal inputted, then return
    const isNum = e.target.value.match(/^(?:\d{1,8}(?:\.\d{0,8})?)?$/);
    if (!isNum) return;
    // Update priority list to calculate the last updated input
    formCopy.priorityList = formCopy.priorityList.sort((a, b) => {
      if (a === inputFieldName) return 1;
      if (b === inputFieldName) return -1;
      else return 0;
    });
    // Update selected input field
    formCopy.inputs[calcmode] = formCopy.inputs[calcmode].map((input) => {
      if (input.name === inputFieldName) {
        input.value = e.target.value;
      }
      return input;
    });

    // If more than two inputs empty do not calculate
    const emptyInputs = formCopy.inputs[calcmode].reduce(
      (acc, nV) => (nV.value === "" ? (acc += 1) : acc),
      0
    );

    // Calculate the last edited input field
    formCopy.inputs[calcmode] = formCopy.inputs[calcmode].map((input) => {
      if (input.name === formCopy.priorityList[0] && emptyInputs <= 1) {
        const calculatedValue = formCopy.calculate(
          formCopy.priorityList[0],
          calcmode
        );
        input.value = Number(calculatedValue).toFixed(2);
      }
      return input;
    });

    // Final set hook, now with calculated value
    setformEQ({ ...formCopy });
  };

请 Whosebug 的好心人...帮帮我!

你的代码有几个问题:

  1. 您正在根据子对象的 name 属性 进行过滤,并且它们都具有相同的名称。始终为对象提供唯一性 id,以便可以轻松区分它们。

  2. 你的过滤逻辑大错特错:

     formCopy.inputs[calcmode] = formCopy.inputs[calcmode].map((input) => {
          if (input.name === inputFieldName) {
            input.value = e.target.value; // < -- Culprit
          }
          return input;
        });
    
    

从不改变内联,始终创建一个新副本。

这就是您的代码 change 函数应有的样子(为清楚起见,我删除了动态键选择):

  const change = (e, id) => {
    const inputFieldName = e.target.name;

    // local copy of array
    const nestedArr = [...qform.nestedObject.standardType];

    // finding item to be updated
    const index = nestedArr.findIndex((i) => i.id === id);

    console.log({ index, inputFieldName, e, id });

    if (index !== -1) {
      const item = nestedArr[index];
      item.value = e.target.value;
      nestedArr[index] = item;

      // deep copy till k depth where k is the key to be updated
      const newObject = {
        ...qform,
        nestedObject: {
          ...qform.nestedObject,
          standardType: [...nestedArr],
        },
      };

      setQform(newObject);
    }}

检查这个例子:Demo