繁体   English   中英

有多个<select>元素在 React 中共享相同的选项?

[英]Have multiple <select> elements share the same options in React?

所以我有一个 React 组件,如:

export default function ExampleComponent() {
    return (
        <div>
            <select required name="select1">
                <option label=" "></option>
                <option value="option1">Option 1</option>
                <option value="option2">Option 2</option>
                <option value="option3">Option 3</option>
            </select>

            <select name="select2">
                <option label=" "></option>
                <option value="option1">Option 1</option>
                <option value="option2">Option 2</option>
                <option value="option3">Option 3</option>
            </select>
        </div>
    );
}

继续进行多个选择...

我想要它,以便当我在任何选择标签中选择一个选项时,它会作为所有其他选项中的一个选项被删除。 如果我更改选定的选项,它就会在所有其他选项中再次可用。 有谁知道我如何在 React 中做到这一点?

您必须使用state来管理值并在两个select之间共享它。

 import React, {useState} from 'react' export default function ExampleComponent() { const [value, setValue] = useState('option0') handleChange = (e) => { setValue(e.target.value) } return ( <div> <select value={value} onChange={handleChange}> <option value="option0"></option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> <select value={value} onChange={handleChange}> <option value="option0"></option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> </div> ); }

你为什么不使用状态? 您可以为选项使用相同的数据源,也可以为所有选择使用相同的事件处理程序。

export default function ExampleComponent() {
  state = {
    options: [
      {
        name: 'Option 1',
        value: 'option1'
      },
      {
        name: 'Option 2',
        value: 'option2'
      },
      {
        name: 'Option 3',
        value: 'option3'
      }
    ]
  };

  onChangeSelect = event => {
    // do something
    this.setState({
      options: this.state.options.filter(
        option => option.value !== event.target.value
      )
    });
  };

  return (
    <div>
      <select required name="select1" onChange={onChangeSelect}>
        <option label=" "></option>
        {this.state.options.map(option => (
          <option value={option.value}>{option.name}</option>
        ))}
      </select>

      <select name="select2" onChange={onChangeSelect}>
        <option label=" "></option>
        {this.state.options.map(option => (
          <option value={option.value}>{option.name}</option>
        ))}
      </select>
    </div>
  );
}

可能有一种更优雅的方法来做到这一点,但我的想法是跟踪哪个select选择了哪个选项,并使用一个名为chosenObjects的对象,然后根据该信息过滤结果。

import React, {useState} from "react";

export default function ExampleComponent() {
    const selectNames = ["select1", "select2"];
    const [options] = useState([
        {
            label: 'Option 1',
            value: 'option1'
        },
        {
            label: 'Option 2',
            value: 'option2'
        },
        {
            label: 'Option 3',
            value: 'option3'
        }
    ]);


    const [chosenOptions, setChosenOptions] = useState({});

    const isChosenByOther = (optionValue, selectName) => {
        for (let key in chosenOptions) {
            if (key !== selectName) {
                if (chosenOptions[key] === optionValue) {
                    return true;
                }
            }
        }
        return false;
    };

    const handleChange = (ev) => {
        setChosenOptions({...chosenOptions, [ev.target.name]: ev.target.value});
    };

    return (
        <div>
            {selectNames.map((name, index) => {
                return (
                    <select name={name} key={index} onChange={handleChange} value={chosenOptions[name] || ''}
                            required={index === 0}>
                        <option value=''/>
                        {options.filter(({value}) => !isChosenByOther(value, name))
                            .map(({label, value}, oIndex) =>
                                <option value={value} key={oIndex}>{label}</option>)
                        }
                    </select>
                )
            })}
        </div>
    );
}

您还option在选择某些内容后有条件地禁用空字符串值option

<div>
    {selectNames.map((name, index) => {
        return (
            <select name={name} key={index} onChange={handleChange} value={chosenOptions[name] || ''}
                    required={index === 0}>
                <option value='' disabled={chosenOptions[name]}>Choose Option</option>
                {options.filter(({value}) => !isChosenByOther(value, name))
                    .map(({label, value}, oIndex) =>
                        <option value={value} key={oIndex}>{label}</option>)
                }
            </select>
        )
    })}
</div>

您需要跟踪多个Select元素的状态,然后有条件地为每个元素渲染选项。

我将使用其他答案中的一些内容并展示如何使其工作。 编辑以保持选项的顺序相同。

import React, {useState} from "react";
function ExampleComponent() {
    const [myState, setMyState] = useState({});
    const options = [
        {
            name: 'Option 1',
            value: 'option1'
        },
        {
            name: 'Option 2',
            value: 'option2'
        },
        {
            name: 'Option 3',
            value: 'option3'
        }
    ]

    // list of select names
    const selectNames = [
        "select1",
        "select2"
    ]

    handleChange = (e) => {
        // update the value for the given select
        myState[e.target.name] = e.target.value
        setMyState(myState)
    }

    const inUseValues = Object.values(myState);

      console.log(inUseValues)

    // get the options for given name
    getOptions = (name) =>
        options.filter(option => !inUseValues.includes(option.value) || myState[name]==option.value)
        .map(option => (
            <option key={option.value} value={option.value}>{option.name}</option>
        ))

    // render all select controls
    const selectRender = selectNames.map(name => (
        <select key={name} required name="{name}" value={myState[name]} onChange={handleChange}>
            <option label=" "></option>
            {getOptions(name)}
        </select>
        ))

    return (
        <div>
            {selectRender}
        </div>
    )

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM