我想在数组中切换对象的属性。该数组如下所示。这是在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
组件的父级传入灯具。
答案 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到index
:fixtures.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
];
要构建新项目:
const newFixture = {
...oldFixture,
winner: /* new value */
};
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))