【问题标题】:React DOM - Form with multiple <select>, remove option from another <select> after choose one optionReact DOM - 具有多个 <select> 的表单,选择一个选项后从另一个 <select> 中删除选项
【发布时间】:2020-02-06 22:49:49
【问题描述】:

我有一个包含 4 个输入的表单,使用来自同一状态的数据。我想要的是,在选择之后,选择选项将从另外 3 个选择中删除。

我尝试了很多东西,在这里很难列出,但简而言之:我创建另一个选定选项列表,用另一个列表过滤玩家数组,映射这个等等。

这种方法的问题是:我不想从选择它的输入中删除选定的项目。所以,我尝试为每个输入创建相同原始列表的副本。但是,我认为这种方式“变通”太多了。

这是我的组件:

import React, { Component } from 'react';

export default class MatchPlayerSelect extends Component {
   state = {
      selectedPlayers: [],
      players: [
         {
            name:"edmiel",
            matches:0,
            wins:0
         },
         {
            name:"willian",
            matches:0,
            wins:0
         },
         {
            name:"gustavo",
            matches:0,
            wins:0
         },
         {
            name:"gabriel",
            matches:0,
            wins:0
         }
     ]
   }

   render() {
      const {players, selectedPlayers} = this.state;

      return (
         <div className="match-player">
            <select onChange={this.setPlayer.bind(this)}>
               <option defaultValue value="">-</option>
               {
                  // i need to filter list here
                  // but this code only list the items on state
                  players.map((player, index) => {
                     return(
                        <option key={index} value={player}>
                           {player.name}
                        </option>
                     )
                  })
               }
            </select>
         </div>
      );
   }

   setPlayer(sender) {      
      this.setState({ selectedPlayer: [...this.state.selectedPlayers, 
      sender.target.value] });
   }

}

我需要所有选择组件渲染每个状态播放器(已经在上面的代码中这样做了)。但是,在选中时,我需要从另一个输入中删除此选项选项,而不会从焦点选择输入中删除。如果在 React 中存在更好的解决方案,请告诉我如何操作。

我需要使用 react jsx 工具或 vanilla js 来执行此操作。没有jquery! 就是这样。

【问题讨论】:

  • 我不明白要做什么,在选择球员时会发生什么?该选项应该消失吗?请编辑您的问题并显示所需的行为。
  • 我上面的问题描述的很好,不知道怎么解释更好:(
  • 你可以只通过 selectedPlayers 过滤玩家,阅读 #filter 和 #includes
  • 我想澄清一下,虽然我评论了几次,但您需要制作一个可生产的示例,向我们展示您的表单与多个选择器,向我们展示您为解决问题所做的一些努力并简要说明您的示例所需的输入和输出以及哪些不起作用,这就是 SO 的工作原理,干杯。

标签: javascript arrays reactjs drop-down-menu state


【解决方案1】:

所以首先,你应该从渲染方法中删除this.selectPlayer.bind(this),这对 React 不利,更多请关注link
在当前情况下,您需要添加一个额外的数组,它应该看起来像:
1. players - 你应该保留所有玩家(这个仅用于过滤)。
2. filteredPlayers - 你应该保留过滤后的播放器(这个服务器用于渲染选项列表)。
3. selectedPlayersIds- 当然,您收集所有选定玩家 ID 的数组。
每次选择玩家时,您将采用players数组并删除所有选定的玩家+新选定的玩家并分配给filteredPlayers数组。
代码片段(selectPlayer 函数)

const selectedPlayersIds= [...this.state.selectedPlayersIds, newPlayer.id];
this.setState({
  filteredPlayers: this.state.players.filter(player => this.selectedPlayerIds.indexOf(player.id) !== -1),
  selectedPlayersIds
})

【讨论】:

  • 这将与多个使用相同的“filteredPlayers”的
【解决方案2】:

使用#Array.filter#Array.includes,此外,您需要对代码进行一些修复以使其正常工作:

  • setPlayer 将密钥更改为selectedPlayers 而不是selectedPlayer
  • 在将 players 数组映射到 option 时,value 属性必须是 player.name 而不是 player
players
  .filter(player => !selectedPlayers.includes(player.name))
  .map((player, index) => (
    <option key={index} value={player.name}>
      {player.name}
    </option>
  ));

完整示例:

class MatchPlayerSelect extends Component {
  state = {
    selectedPlayers: [],
    players: [
      {
        name: 'edmiel',
        matches: 0,
        wins: 0
      },
      {
        name: 'willian',
        matches: 0,
        wins: 0
      },
      {
        name: 'gustavo',
        matches: 0,
        wins: 0
      },
      {
        name: 'gabriel',
        matches: 0,
        wins: 0
      }
    ]
  };

  render() {
    const { players, selectedPlayers } = this.state;

    return (
      <div className="match-player">
        <select onChange={this.setPlayer}>
          <option defaultValue value="">
            -
          </option>
          {players
            .filter(player => !selectedPlayers.includes(player.name))
            .map((player, index) => (
              <option key={index} value={player.name}>
                {player.name}
              </option>
            ))}
        </select>
        <div>{JSON.stringify(selectedPlayers)}</div>
      </div>
    );
  }

  setPlayer = sender => {
    const { selectedPlayers } = this.state;
    this.setState({
      selectedPlayers: [...selectedPlayers, sender.target.value]
    });
  };
}
ReactDOM.render(<MatchPlayerSelect />, document.getElementById('root'));

【讨论】:

  • 很好,我已经做到了。这种方法的问题是从当前焦点 上下文中维护所有可能的选项。目前我在 上选择了一个玩家(有 4 个选项),所有其他的
  • 不,我没听懂,你的意思是你有多重选择吗?你没有在问题中提到它。按照事先的建议,做一个期望的行为示例。
  • 是的,我有一个“多选表单”在问题的标题中。我将编辑问题以使其更具体。我有 4 个来自同一州的 选项之间进行交互。
  • 我在您的问题和任何形式中都看不到任何可生产的示例,您只是更改了标题。请阅读How do I ask a good question?How to create a Minimal, Reproducible Example
猜你喜欢
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多