反应下拉菜单选择-基于箭头按钮的增加或减少

时间:2018-07-23 22:49:37

标签: javascript reactjs ecmascript-6

我有一个下拉输入。单击输入旁边的向左或向右箭头按钮时,我想向前或向后移动当前选择的选项。单击下拉列表本身并选择一个选项时,它还应该跟踪该选项。

使用e.target.value(和控制台日志)单击时,我能够捕获当前所选对象的值,并且单击箭头按钮时,我能够增加或减少状态的计数(和控制台日志),但是我不确定将两者结合在一起的最佳方法(在数组中“ count”位置索引处显示项目?)

这是我的代码:

class DropdownMenu extends Component {
  state = {
    // Select options
    options: [
      { name: 'Item 1', label: 'Item 1' },
      { name: 'Item 2', label: 'Item 2' },
      { name: 'Item 3', label: 'Item 3' },
      { name: 'Item 4', label: 'Item 4' },
      { name: 'Item 5', label: 'Item 5' }
    ],
    value: 'select', // this should be the initial item ('Item 1')
    count: 0
  };

  change = e => {
    this.setState({ value: e.target.value }, console.log(this.state));
  };

  handleIncrement = () => {
    this.setState(
      {
        count: this.state.count + 1
      },
      () => {
        console.log(this.state);
      }
    );
  };

  handleDecrement = () => {
    this.setState(
      {
        count: this.state.count - 1
      },
      () => {
        console.log(this.state);
      }
    );
  };

  // Here I map over the options in state

  dropdown = () => (
    <div className="dropdown position-relative">
      <select onChange={this.change} value={this.state.value}>
        {this.state.options.map((option, index) => {
          return (
            <option key={index} name={option.name} value={option.name}>
              {option.label}
            </option>
          );
        })}
      </select>
      <div className="descend">
        <img className="icon" src={descendIcon} alt="" />
      </div>
    </div>
  );

  // I want to use these arrows to increment or decrement the selection on the drop down

  leftArrow = icon => (
    <button
      type="button"
      className="btn btn-2"
      onClick={this.handleIncrement}
    >
      <img className="icon" src={icon} alt="left arrow" />
    </button>
  );

  rightArrow = icon => (
    <button
      type="button"
      className="btn btn-2"
      onClick={this.handleDecrement}
    >
      <img className="icon" src={icon} alt="" />
    </button>
  );

  render() {
    return (
      <div className="flex flex-row">
        <div className="flex-grow">{this.dropdown()}</div>
        <div>
          {this.leftArrow(leftIcon)}
          {this.rightArrow(rightIcon)}
        </div>
      </div>
    );
  }
}

export default DropdownMenu;

4 个答案:

答案 0 :(得分:1)

在此示例中,this.state.count存储选定的options索引。如果我们将this.state.count设置为select菜单的value,那么当状态更新时,select将重新呈现并显示与更新后的计数匹配的选项。

实时演示:https://codesandbox.io/s/38v727rrm

class DropdownMenu extends React.Component {
    state = {
        // Select options
        options: [
            { name: 'Item 1', label: 'Item 1' },
            { name: 'Item 2', label: 'Item 2' },
            { name: 'Item 3', label: 'Item 3' },
            { name: 'Item 4', label: 'Item 4' },
            { name: 'Item 5', label: 'Item 5' }
        ],
        count: 0
    };
    change = e => {
        this.setState({ count: Number(e.target.value) });
    };
    handleIncrement = () => {
        const c = this.state.count;
        const len = this.state.options.length - 1;
        let count = (c + 1 > len) ? c : c + 1;
        this.setState({ count });
    };
    handleDecrement = () => {
        const c = this.state.count;
        let count = (c - 1 < 0) ? c : c - 1;
        this.setState({ count });
    };
    dropdown = () => (
        <div className="dropdown position-relative">
            <select onChange={this.change} value={this.state.count}>
                {this.state.options.map((option, index) => (
                    <option key={index} name={option.name} value={index}>
                        {option.label}
                    </option>
                ))}
            </select>
            <div className="descend">
                <img className="icon" src="" alt="" />
            </div>
        </div>
    );
    leftArrow = icon => (
        <button
            type="button"
            className="btn btn-2"
            onClick={this.handleDecrement}
            >
            <img className="icon" src={icon} alt="left arrow" />
        </button>
    );
    rightArrow = icon => (
        <button
            type="button"
            className="btn btn-2"
            onClick={this.handleIncrement}
            >
            <img className="icon" src={icon} alt="right arrow" />
        </button>
    );    
    render() {
        return (
            <div className="flex flex-row">
                <div className="flex-grow">{this.dropdown()}</div>
                <div>
                    {this.leftArrow('leftIcon')}
                    {this.rightArrow('rightIcon')}
                </div>
            </div>
        );
    }
}

答案 1 :(得分:0)

请勿同时在您的状态下存储countvalue,因为这样您将有两个应选择的真实来源。只需存储count,在您将得到value的任何地方,都改为获取options[count]

答案 2 :(得分:0)

好,我想念您的问题,所以您可以使用约瑟夫(Joseph)描述的逻辑来做到这一点。 使用options [index]获取价值,并始终更新索引

外观:https://codesandbox.io/s/zpwvjxjol

答案 3 :(得分:-1)

看看React recommended way to handle setState

由于React可以批处理setState来提高性能,所以您不能仅仅依靠this.state.count来作为更新状态的起点。相反,您需要调用传递prevState作为参数之一的setState,并使用prevState.count +1