📜  添加价值道具后,react-select 无法删除选定的选项 (1)

📅  最后修改于: 2023-12-03 15:27:01.612000             🧑  作者: Mango

添加价值道具后,react-select 无法删除选定的选项

问题描述

在使用 react-select 组件时,如果在选项中添加了价值道具,例如删除按钮等,可能会导致无法删除选定的选项。

原因分析

react-select 是基于 react 实现的下拉框组件,其选中选项的状态是通过 props 传递给组件的。如果选中的选项上添加了价值道具,会影响到组件对选中状态的判断。在删除按钮被点击时,可能会触发选项的点击事件,进而导致组件无法正确处理选中状态的改变。

解决方法
1. 不要在选项中添加价值道具

如果价值道具对业务需求不是必要的,建议不要在选项中添加价值道具,避免出现问题。

2. 自定义删除选项的处理函数

可以通过自定义删除选项的处理函数,避免使用 react-select 自带的删除功能。具体实现方法如下:

import React, { useState } from 'react';
import Select from 'react-select';

const App = () => {
  const [options, setOptions] = useState([
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
    { value: 'option3', label: 'Option 3' },
    { value: 'option4', label: 'Option 4' },
  ]);

  const handleDeleteOption = (value) => {
    setOptions(options.filter((option) => option.value !== value));
  };

  const customStyles = {
    control: (base, state) => ({
      ...base,
      borderColor: state.isFocused ? '#80bdff' : base.borderColor,
      boxShadow: state.isFocused ? '0 0 0 0.2rem rgba(0, 123, 255, 0.25)' : base.boxShadow,
    }),
  };

  const optionComponents = options.map((option) => ({
    ...option,
    // 添加删除按钮
    label: (
      <>
        {option.label}
        <button onClick={() => handleDeleteOption(option.value)}>Delete</button>
      </>
    ),
  }));

  return <Select options={optionComponents} styles={customStyles} isMulti />;
};

export default App;
3. 修改 react-select 组件源码

如果业务需求必须要在选项中添加价值道具,且以上两种解决方法均无法满足需求,可以考虑修改 react-select 组件源码。具体方法如下:

  1. 找到 react-select 组件中与选项相关的代码,通常在 src/Select.js 文件中。
  2. 找到处理选项点击事件的方法,通常是 handleOptionClick
  3. 在该方法中添加对价值道具的处理逻辑。例如,在处理选项点击事件之前,可以判断选项是否包含某个类名,如果包含,则不处理选项点击事件。
handleOptionClick(option, event) {
  if (!this.props.isDisabled && !option.isDisabled) {
    if (option.isFixed) {
      return;
    }
    if (!this.props.closeMenuOnSelect) {
      event.stopPropagation();
    }
    const selectedOption = this.state.selectValue.find((selectedOption) => selectedOption.value === option.value);
    if (this.props.isMulti) {
      if (selectedOption) {
        const value = this.state.selectValue.filter((option) => option.value !== selectedOption.value);
        this.callOnChange(value);
      } else {
        const value = [...this.state.selectValue, option];
        this.callOnChange(value);
      }
      // 判断选项是否包含某个类名,如果包含,则不处理选项点击事件
      if (event.target.classList.contains('delete-button')) {
        return;
      }
    } else {
      this.callOnChange(option);
    }
    this.onSelectResetsInput();
  }
},
  1. 修改选项的渲染方式,使其可以包含价值道具。
renderOption(option, key) {
  if (option.type === 'group') {
    return (
      <components.Group key={key} {...option}>
        {option.options.map((nestedOption, index) => this.renderOption(nestedOption, `${key}-${index}`))}
      </components.Group>
    );
  } else {
    return (
      // 添加类名,用于判断能否处理选项点击事件
      <components.Option key={key} {...option} className="custom-option">
        {option.label}
        <button className="delete-button" onClick={() => this.handleDeleteOption(option.value)}>Delete</button>
      </components.Option>
    );
  }
},

注意:修改 react-select 组件源码有一定的风险,需要慎重考虑。建议使用自定义删除选项的处理函数来解决问题。如果不得已需要修改源码,请注意维护成本和风险,并且建议先 fork 一份源码进行修改。