切换数组中的项目反应

时间:2019-01-23 09:48:00

标签: javascript arrays reactjs ecmascript-6

我想在数组中切换对象的属性。该数组如下所示。这是在React组件中使用的,当用户单击按钮时,我想切换获胜者。

const initialFixtures = [{
    teams: {
      home: 'Liverpool',
      away: 'Manchester Utd'
    },
    winner: 'Liverpool'
  },
  {
    teams: {
      home: 'Chelsea',
      away: 'Fulham'
    },
    winner: 'Fulham'
  }, ,
  {
    teams: {
      home: 'Arsenal',
      away: 'Tottenham'
    },
    winner: 'Arsenal'
  }
];

我的反应代码看起来像这样

function Parent = () => {

  const [fixtures, setUpdateFixtures] = useState(initialFixtures)
  const toggleWinner = (index) => {
     const updatedFixtures = fixtures.map((fixture, i) => {
           if (i === index) {
                return {
                    ...fixture,
                    winner: fixture.winner === home ? away : home,
                };
            } else {
                return fixture;
            }
     }) 
     setUpdateFixtures(updatedFixtures);
  }

  return <Fixtures fixtures={fixtures} toggleWinner={toggleWinner} />;

}


function Fixtures = ({ fixtures, toggleWinner }) => { 
  fixtures.map((fixture, index) => ( 
    <div>
        <p>{fixture.winner} </p>
    <button onClick = {() => toggleWinner(index)}> Change Winner</button> 
    </div>
  ))
}

代码有效,但感觉有点太多了。我敢肯定,这样做有更好更好的方法。有人可以建议吗?出于架构原因,我确实需要从Fixture组件的父级传入灯具。

6 个答案:

答案 0 :(得分:2)

const updatedFixtures = [...fixtures];
const fixture = updatedFixtures[i];
updatedFixtures[i] = {
  ...fixture,
  winner: fixture.winner === fixture.teams.home ? fixture.teams.away : fixture.teams.home,
};

答案 1 :(得分:1)

您可以slice将灯具阵列分为三部分:

  • 从0到indexfixtures.slice(0, index)。这部分将原封不动地移到新数组。

  • index上的单个项目。该零件/项目由于更改而被丢弃,并替换了新项目。

  • 数组的其余部分:fixtures.slice(index + 1)

接下来,将它们放入一个新数组:

const newFixtures = [
    ...fixtures.slice(0, index),    // part 1
    {/* new item at 'index' */},    // part 2
    ...fixtures.slice(index + 1)    // part 3
];

要构建新项目:

  • 使用spread operator

    const newFixture = {
        ...oldFixture,
        winner: /* new value */
    };
    
  • 使用Object.assign

    const newFixture = Object.assign({}, oldFixture, {
        winner: /* new value */
    });
    

答案 2 :(得分:0)

      const toggleWinner = (index) => {
        let  updatedFixtures = [...fixtures].splice(index, 1, {...fixtures[index],
         winner: fixtures[index].winner === fixtures[index].teams.home
         ? fixtures[index].teams.away : fixtures[index].teams.home})

        setUpdateFixtures(updatedFixtures);
      }

答案 3 :(得分:0)

您可以使用immer等库来轻松更新嵌套状态。

const initialFixtures = [{
    teams: {
      home: 'Liverpool',
      away: 'Manchester Utd'
    },
    winner: 'Liverpool'
  },
  {
    teams: {
      home: 'Chelsea',
      away: 'Fulham'
    },
    winner: 'Fulham'
  }, ,
  {
    teams: {
      home: 'Arsenal',
      away: 'Tottenham'
    },
    winner: 'Arsenal'
  }
];

const newState = immer.default(initialFixtures, draft => {
  draft[1].winner = "something";
});

console.log(newState);
<script src="https://cdn.jsdelivr.net/npm/immer@1.0.1/dist/immer.umd.js"></script>

答案 4 :(得分:0)

如果您以这种方式编写代码-这样就可以完成工作。

const toggleWinner = index => {
    const { winner, teams: { home, away } } = fixtures[index];
    fixtures[index].winner = winner === home ? away : home;

    setUpdateFixtures([...fixtures]);
};

设置一组新的夹具状态足以触发render组件上的Fixtures

我为您制作了一个working example

答案 5 :(得分:0)

如果您愿意使用基于类的方法,则可以尝试如下操作:

  • 创建一个拥有团队财产价值的类。
  • 在此类中创建一个布尔属性,例如isHomeWinner。此属性将决定获胜者。
  • 然后创建一个吸气剂属性winner,它将查找this.isHomeWinner并给出必要的值。
  • 这将使您拥有干净的toggle功能:this.isHomeWinner = !this.isHomeWinner

您也可以将toggleWinner编写为:

const toggleWinner = (index) => {
  const newArr = initialFixtures.slice();
  newArr[index].toggle();
  return newArr;
};

这看起来很干净而且声明性的。注意,如果需要不变性,那么仅这是必需的。如果您对更改值感到满意,只需将fixture.toggle传递给您的react组件。您可能需要绑定上下文,但这应该也可以。

所以它看起来像:

function Fixtures = ({ fixtures, toggleWinner }) => { 
  fixtures.map((fixture, index) => ( 
    <div>
      <p>{fixture.winner} </p>
      <button onClick = {() => fixture.toggle() }> Change Winner</button> 

      // or
      // <button onClick = { fixture.toggle.bind(fixture) }> Change Winner</button> 
    </div>
  ))
}

以下是类及其用法的示例:

class Fixtures {
  constructor(home, away, isHomeWinner) {
    this.team = {
      home,
      away
    };
    this.isHomeWinner = isHomeWinner === undefined ? true : isHomeWinner;
  }

  get winner() {
    return this.isHomeWinner ? this.team.home : this.team.away;
  }

  toggle() {
    this.isHomeWinner = !this.isHomeWinner
  }
}

let initialFixtures = [
  new Fixtures('Liverpool', 'Manchester Utd'),
  new Fixtures('Chelsea', 'Fulham', false),
  new Fixtures('Arsenal', 'Tottenham'),
];

const toggleWinner = (index) => {
  const newArr = initialFixtures.slice();
  newArr[index].toggle();
  return newArr;
};

initialFixtures.forEach((fixture) => console.log(fixture.winner))
console.log('----------------')
initialFixtures = toggleWinner(1);
initialFixtures.forEach((fixture) => console.log(fixture.winner))

initialFixtures = toggleWinner(2);
console.log('----------------')
initialFixtures.forEach((fixture) => console.log(fixture.winner))