Javascript 为什么我的状态更新会覆盖现有数据值?

Javascript 为什么我的状态更新会覆盖现有数据值?,javascript,reactjs,Javascript,Reactjs,下面,我试图复制用户数据的当前状态,以及从一个json文件中提取的一个新发票模板的副本,该文件的键值对全部为空 然后,我将templates invoiceID更改为比idx多1(这是一个从子组件发送的数值,即状态中所有发票的长度) 最后,我获取用户数据的副本并添加到新模板上,然后将新用户数据保存回状态,以便在我的列表中进行更新 createInvoice = idx => { let newUserData = this.state.userData; let tem

下面,我试图复制用户数据的当前状态,以及从一个json文件中提取的一个新发票模板的副本,该文件的键值对全部为空

然后,我将templates invoiceID更改为比idx多1(这是一个从子组件发送的数值,即状态中所有发票的长度)

最后,我获取用户数据的副本并添加到新模板上,然后将新用户数据保存回状态,以便在我的列表中进行更新

  createInvoice = idx => {
    let newUserData = this.state.userData;
    let template = UsersJSON[0].invoices[0];

    template.invoiceID = idx + 1;
    newUserData.invoices.push(template);

    this.setState({
      userData: newUserData
    });
  }
这是我登录时所有数据的当前状态:

单击“新建发票+一次”后:

在多次单击“新建发票”后,问题开始出现:

只有所有新的发票ID不断更新为最新和最大的ID。我真的不知道为什么会这样。任何帮助都将不胜感激

指向我在github上的项目的链接(查看发票分支,而不是主控):

您希望在更新状态对象之前复制状态对象(在JS数组中是对象)。也许
让newUserData=[…this.state.userData]
是避免此错误的方法,但您可能需要一个“深度副本”

有关此主题的更多信息,请参阅。

问题
  • 您没有正确地为状态和响应协调创建新数组引用
  • 您还将修改模板引用对象
  • 代码


    我想我们会从你的应用程序中获得更广阔的视野。一般来说,将我们联系起来是不够的。有关setState异步特性的详细信息,请参阅。当然可以。JSON(第2行->第39行):App.jsx(函数名为第103行->第113行)invoice.jsx(onClick处理程序名为第162行的子组件)。这里没有。我认为这是正确的答案,但它是说我不能遍历我的…prevState.userData(我假设这是因为这是一个对象,并且…prevState.userData.invoices是我们可以遍历的数组?@BrentAnderson啊,非常正确,
    userData
    是一个需要复制
    invoices
    数组的对象,很抱歉弄错了。我已经更新了答案中的代码。哇,谢谢你的帮助!我认为我没有像那样直接改变我的状态,因为我把它复制到一个变量中。有没有办法让非反作用y解决方案发挥作用?这是一个无法纠正的错误。@BrentAnderson是的,对不起,同样的问题,我没有深入到数组副本。更新了。@BrentAnderson很棒。如果解决了,请将答案标记为已接受,如果解释有帮助,也请进行投票。干杯
    createInvoice = idx => {
      let newUserData = this.state.userData; // <-- saved state reference
      let template = UsersJSON[0].invoices[0];
    
      template.invoiceID = idx + 1; // <-- template mutation
      newUserData.invoices.push(template); // <-- mutated state
    
      this.setState({
        userData: newUserData // <-- saved state reference back into state
      });
    }
    
    createInvoice = idx => {
      let newInvoices = [...this.state.userData.invoices]; // <-- create a new array reference
      let template = {
        ...UsersJSON[0].invoices[0], // <-- create new template object reference
      };
    
      template.invoiceID = idx + 1;
      newInvoices.push(template);
    
      this.setState({
        userData: {
          ...state.userData,
          invoices: newInvoices,
        }
      });
    }
    
    createInvoice = idx => {
      this.setState(prevState => ({
        userData: {
          ...prevState.userData,
          invoices: [
            ...prevState.userData.invoices,
            {
              ...UsersJSON[0].invoices[0],
              invoiceID: idx + 1,
            },
          ],
        },
      }));
    }