我正在尝试创建此功能,该功能可用于将 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 ],
}
})
}
答案 0 :(得分:1)
阅读完所有想法后,我想出了一个解决方案。这是我现在拥有的:
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 ],
}
})
}
再次感谢大家
答案 1 :(得分:0)
我会尝试类似的
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>
答案 2 :(得分:0)
这是另一种解决方案,不是那么简单,也许不是那么易读,但它可行:)
使用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>