如何在用于状态的对象中删除和添加数组元素?



我正在尝试创建这个函数,该函数可用于将this.state.user.id添加到this.state.players.team1,同时还检查this.state.players中的所有其他数组以删除this.state.user.id(如果存在(。

以下是一些上下文:

// function is used for onClick()
// this.state.players = { 
//     team1: [1, 2], 
//     team2: [5, 7] 
// }
// this.state.user.id = 7
// (team) parameter is passed with "team1" or "team2" depending on situation

下面是我尝试编写的函数。 有没有更好的方法来写出来?this.setState 异步执行,这会破坏我的函数。

onJoinTeam(team) {
// remove player id from any id
this.setState({
players: 
Object.entries(this.state.players).map(key => {
return key[1].filter(player => player !== this.state.user.id)
})
})
// add this.state.user.id to this.state.players
this.setState({  
players: { 
...this.state.players, 
[team]: [ ...this.state.players[team], this.state.user.id ], 
}
})
}

在阅读了您的所有想法后,我想出了一个解决方案。这是我现在拥有的:

onJoinTeam(team) {
const { players } = this.state;
const newTeams = {}
Object.entries(players).map(([key, value]) => {
const filteredTeamObj = { 
[key]: value.filter(player => player !== this.state.user.id) }
return Object.assign(newTeams, filteredTeamObj)
})
this.setState({
players: { 
...newTeams, 
[team]: [ ...this.state.players[team], this.state.user.id ], 
}
})
}

再次感谢大家

这是另一种解决方案,不是那么简单,也许不是那么可读,但它:) 使用Object.entries我们创建一个地图。在执行此操作时,我们正在检查team是否等于我们的key。如果是,我们将id添加到我们的key,如果不是,我们会过滤掉id。最后一步是使用此数组创建对象,并reduce.

class App extends React.Component {
state = {
players: {
team1: [1, 2],
team2: [5, 7],
team3: [9, 6, 7],
},
id: 7,
}
componentDidMount() {
this.change( "team1" );
}
change = team => {
const { players, id } = this.state;
const newPlayers = Object.entries(players).map(([key,value]) =>
team === key
? { [key] : [ ...value, id ] }
: { [key]: value.filter(player => player !== id) }
).reduce( ( obj, item) => ({
...obj,
...item,
}) );

this.setState({players: newPlayers})
}
render() {
console.log( this.state.players );
return (
<div>
Look the console to see the old and new value of the players.
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

我会尝试类似的东西

const { players } = this.state;
for (const team in players) {
const teamPlayers = players[team];
const playerIndex = teamPlayers.findIndex(tp => tp === userId);
if (playerIndex !== -1) {
teamPlayers.splice(playerIndex, 1);
break;
}
}
players[newTeam].push(userId);
this.setState({ players });

可以在此代码段中看到实际操作

class App extends React.Component {
state = {
players: {
team1: [1, 2, 3],
team2: [4, 5, 6],
},
};
render() {
return (
<div>
<pre>{JSON.stringify(this.state, null, 4)}</pre>
<form onSubmit={(e) => this.onJoinTeam(e)}>
<label>User ID</label>
<input name="userId" type="number" min="1" max="6" step="1" />
<br />
<label>New Team</label>
<select name="newTeam">
<option value="team1">Team 1</option>
<option value="team2">Team 2</option>
</select>
<br />
<button type="submit">Move player</button>
</form>
</div>
);
}
onJoinTeam(e) {
e.preventDefault();
const newTeam = e.currentTarget.newTeam.value;
const userId = parseInt(e.currentTarget.userId.value, 10);
const { players } = this.state;
for (const team in players) {
const teamPlayers = players[team];
const playerIndex = teamPlayers.findIndex(tp => tp === userId);
if (playerIndex !== -1) {
teamPlayers.splice(playerIndex, 1);
break;
}
}
players[newTeam].push(userId);
this.setState({ players });
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>