简体   繁体   English

React 中的数组正在发生变异

[英]Array in React being mutated

I've read several entries on keeping arrays from being mutated in React, but I can't figure out why my original array is being mutated.我已经阅读了几个关于防止数组在 React 中发生变异的条目,但我不明白为什么我的原始数组发生了变异。 In the componentDidMount, I'm going to the database and retrieving win-loss records for each week and saving the records to state.在 componentDidMount 中,我将转到数据库并检索每周的输赢记录并将记录保存到状态。 (Each week a team plays three games.) (每周一个团队打三场比赛。)

async componentDidMount() {
    document.body.style.background = '#9bcaf1';
    await this.getInitialStats();
    this.processStats();
  }

  async getInitialStats(): Promise<void> {
    const allRecords: TeamWeek[] = await getAllResults();
    this.setState({
      allRecords,
    });
  }

Then I call a second function that takes each team's record for the week and combines them into one record.然后我调用第二个函数,该函数获取每周每个团队的记录并将它们组合成一个记录。 So if a team has lost all three games in each of three weeks, that should combine to one record that shows the team lost nine games.因此,如果一支球队在三周内每场都输掉了三场比赛,那么这应该合并为一个记录,显示该球队输掉了九场比赛。 I save that as a separate state variable.我将其保存为单独的状态变量。 However the original state array is being mutated as well, even though I thought I was cloning the array.然而,原始状态数组也在发生变异,即使我认为我是在克隆数组。 I can do a push into the cloned array, and it works correctly, but something with the function is screwing things up.我可以推入克隆的数组,并且它可以正常工作,但是该函数的某些内容将事情搞砸了。

processStats(): void {
    const allRecordsClone = [...this.state.allRecords];
    const combinedRecords: TeamWeek[] = calculateOverallStats(allRecordsClone);
    this.setState({
      combinedRecords,
    });
  }
export const calculateOverallStats = (allRecords: TeamWeek[]): TeamWeek[] => {
  const allRecordsClone = [...allRecords];
  const combinedRecs: TeamWeek[] = [];
  const teamNamesCollected: string[] = [];

  // Combine wins, losses, ties, points
  allRecordsClone.forEach((rec) => {
    const { team_name, wins, losses, ties, total_points } = rec;
    if (!teamNamesCollected.includes(team_name)) {
      combinedRecs.push(rec);
      teamNamesCollected.push(team_name);
    } else {
      const teamIndex = combinedRecs.findIndex((combRec) => combRec.team_name === team_name);
      combinedRecs[teamIndex].wins += wins;
      combinedRecs[teamIndex].losses += losses;
      combinedRecs[teamIndex].ties += ties;
      combinedRecs[teamIndex].total_points += total_points;
    }
  });
  return allRecordsClone;
};

Any thoughts?有什么想法吗? I cannot figure this out.我无法弄清楚这一点。

Copying an array via spread still creates references to any objects included in the array.通过 spread 复制数组仍然会创建对数组中包含的任何对象的引用。

 const array1 = [1, {a: 2}, [3,4]]; const array2 = [...array1]; array2[0] = "unchanged in array1"; array2[1].a = "changed in both"; array2[2][0] = "arrays are Objects"; console.log('array1: ', array1); // array1: [1, {"a": "changed in both"}, ["arrays are Objects", 4]] console.log('array2: ', array2); // array2: ["unchanged in array1", {"a": "changed in both"}, ["arrays are Objects", 4]]

Given that, you'll need to use Object.assign() or spread each object or array before pushing into the combinedArray.鉴于此,在推入组合数组之前,您需要使用Object.assign()或传播每个对象或数组。

The React docs cover this issue here: Immutability Helpers React 文档在这里介绍了这个问题: Immutability Helpers

@pilchard's answer is correct. @pilchard 的回答是正确的。 First you need to create copy of each property or element of array, and then push it to parent combined array.首先,您需要创建数组的每个属性或元素的副本,然后将其推送到父组合数组。 You need can use either of Object.assign() or spread operator to do this.您需要可以使用Object.assign()或 spread 运算符来执行此操作。

Object spread vs. Object.assign 对象传播与 Object.assign

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM