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

时间:2018-08-23 12:17:29

标签: javascript reactjs

我正在尝试创建此功能,该功能可用于将 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 ], 
        }
    })
}

3 个答案:

答案 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>