ReactJS Patternfly 减少下拉菜单的重复代码

ReactJS Patternfly reduce duplicated code for dropdowns

您好,我有 2 个下拉菜单,但为此我正在使用它管理 2 个状态。请帮助我减少重复代码。假设,如果我想有 10 个下拉列表,那么我的状态数和相同的方法会重复相同的。如果有办法重构代码以减少状态和方法的数量会更好。

注意:我有一个基于 class 的组件

this.state = {
            isOpen: false,
            selected: null,
            isDisabled: false,
            isOpen1: false,
            selected1: null,
            isDisabled1: false,
           
            isOpen2: false,
            selected2: null,
            isDisabled2: false, }

内部构造函数



  this.options = [
            <SelectOption key={0} value={hourTxt} isPlaceholder />,
            <SelectOption key={1} value={weekTxt} />,
            <SelectOption key={2} value={dayTxt} />,
            <SelectOption key={3} value={neverTxt} />, 
          ];

          this.options1 = [
            <SelectOption key={0} value={hourTxt} />,
            <SelectOption key={1} value={weekTxt} />,
            <SelectOption key={2} value={dayTxt} isPlaceholder />,
            <SelectOption key={3} value={neverTxt} />, 
          ];

     
      this.onToggle = (isOpen) => {
        this.setState({
          isOpen
        });
      };

      this.onToggle1 = isOpen1 => {
        this.setState({
          isOpen1
        });
      };

this.onSelect = (event, selection, isPlaceholder) => {
        if (isPlaceholder){

         this.clearSelection();
        }
        else {
          this.setState({
            selected: selection,
            isOpen: false
          },() => { this.postSelectData()

          });
        }
      };

      this.onSelect1 = (event, selection, isPlaceholder) => {
        if (isPlaceholder) this.clearSelection1();
        else {
          this.setState({
            selected1: selection,
            isOpen1: false
          },() => { this.postSelectData()

          });
        }
      };

 this.clearSelection = () => {
        this.setState({
          selected: null,
          isOpen: false
          },() => { this.postSelectData()
          });
       
      };

      this.clearSelection1 = () => {
        this.setState({
          selected1: null,
          isOpen1: false
        },() => { this.postSelectData()
        });
     
    };

渲染下()

const {isOpen, selected,isOpen1, selected1} = this.state

在return()

之下

 <Select
        
          variant={SelectVariant.single}
          onToggle={this.onToggle}
          onSelect={this.onSelect}
          selections={selected}
          isOpen={isOpen}
         
          
        >
         {this.options}
         
        </Select>
 <Select
              variant={SelectVariant.single}
              onToggle={this.onToggle1}
              onSelect={this.onSelect1}
              selections={selected1}
              isOpen={isOpen1}
              
            >
              {this.options1}
            </Select>

为避免代码重复,您可以将重复的逻辑抽象为一个组件,然后创建该组件的多个实例。可以重复使用多少,不能重复使用多少取决于手头的具体要求。

对于您的情况,您可以创建一个 Dropdown 组件,其中包含所有静态部分、通用逻辑和相关的处理函数。 反过来,每个实例特定的所有内容都必须由父组件管理并传递给下拉组件(通常作为道具)。

下面的代码片段可能会帮助您实现您的目标。它是一个基本的下拉组件,提供 enabling/disabling 切换(通用逻辑)并包含所有静态部分(例如,<select>,默认值)。父组件 (App) 通过将细节(标签、选项、onChange 操作)作为道具传递给它来呈现 Dropdown 组件的多个实例。通过 onChange 操作,父组件中的状态将更新为在任一下拉列表中最后选择的值。

const { useState } = React;

const Dropdown = (props) => {
  const [disabled, setDisabled] = useState(false);
  return (
    <div>
      {props.label}
      <button onClick={() => setDisabled(!disabled)}>{disabled ? "enable" : "disable"}</button>
      <br />
      <select onChange={(e) => props.action(e.target.value)} disabled={disabled}>
        <option value="default">I am a default value</option>
        {props.options.map((o) => (
          <option value={o.value}>{o.label}</option>
        ))}
      </select>
    </div>
  );
};
const App = () => {
  const dropdown1 = {
    label: "My first Dropdown",
    options: [
      { value: "value1", label: "entry1" },
      { value: "value2", label: "entry2" },
      { value: "value3", label: "entry3" },
    ],
    action: (val) => setLastSelectedValue(val),
  };

  const dropdown2 = {
    label: "My second Dropdown",
    options: [
      { value: "value4", label: "entry4" },
      { value: "value5", label: "entry5" },
      { value: "value6", label: "entry6" },
    ],
    action: (val) => setLastSelectedValue(val),
  };

  const [lastSelectedValue, setLastSelectedValue] = useState();

  return (
    <div>
      <Dropdown {...dropdown1} />
      <Dropdown {...dropdown2} />
      {lastSelectedValue && <p>Last selected value: {lastSelectedValue}</p>}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>