【问题标题】:Dynamically Generated React Controlled Inputs动态生成的反应控制输入
【发布时间】:2021-01-11 09:45:24
【问题描述】:

我有一个窗口,每次单击按钮时都会生成一组 3 个 HTML 组合框(选择框)。 让我们说类别,子类别和数据。子类别中的选项和数据根据其先前选择的值动态呈现。

我将选定的值存储为对象数组,例如

 const [exerciseData, setExerciseData] = useState([[]]);

样本数据:

exerciseData : [
  //first group 
    [
      category:"",
      subcategory:"",
      name:""
    ],
    //second group
    [
      category:"",
      subcategory:"",
      name:""
    ]

]

所以字面上的第一组输入可以由exerciseData[0] 表示,接下来由exerciseData[1].category 等表示。

问题是我希望用户可以对组进行重新排序,例如上移 1 个组或下移 1 个组。所以我需要选择框成为受控元素。但是我该如何设置呢?

我试过这样:

<select name="category" value={exerciseData[i].category} ... > {options} </select>

当我这样给出时,选择框的值无法更改。它始终保持默认值。

任何建议将不胜感激 提前致谢

【问题讨论】:

  • “基于其先前选择的值”是什么意思?基于category 值?

标签: javascript reactjs input drop-down-menu combobox


【解决方案1】:

要控制输入,您需要通过状态手动处理输入值。在您的示例中,输入值似乎是固定/静态的。

以下 sn-p 是如何在 React 中创建受控select 输入的示例。

更新:

做了一个完整的演示sn-p。请让我知道这是否是您想要的。

const {useState, useCallback, Fragment} = React;

const categories = [
  {
    id: 'CAT.1',
    data: [
      {
        id: 'CAT.1 SUB.A',
        data: [
          {id: 'CAT.1 SUB.A OPT.1'},
          {id: 'CAT.1 SUB.A OPT.2'},
          {id: 'CAT.1 SUB.A OPT.3'}
        ]
      },
      {
        id: 'CAT.1 SUB.B',
        data: [
          {id: 'CAT.1 SUB.B OPT.1'},
          {id: 'CAT.1 SUB.B OPT.2'},
          {id: 'CAT.1 SUB.B OPT.3'}
        ]
      }
    ]
  },
  {
    id: 'CAT.2',
    data: [
      {
        id: 'CAT.2 SUB.A',
        data: [
          {id: 'CAT.2 SUB.A OPT.1'},
          {id: 'CAT.2 SUB.A OPT.2'},
          {id: 'CAT.2 SUB.A OPT.3'}
        ]
      },
      {
        id: 'CAT.2 SUB.B',
        data: [
          {id: 'CAT.2 SUB.B OPT.1'},
          {id: 'CAT.2 SUB.B OPT.2'},
          {id: 'CAT.2 SUB.B OPT.3'}
        ]
      }
    ]
  },
];

function Select(props) {
  const {
    name,
    options = [],
    onIndex
  } = props;

  const [value, setValue] = useState(options[0] && options[0].id);
  
  const onChangeHandler = useCallback((e) => {
    onIndex && onIndex(options.findIndex((item) => item.id === e.target.value));
    setValue(e.target.value);
  }, [onIndex, options]);
  
  return (
      <label>
        {name}:
        <select value={value} onChange={onChangeHandler}>
          {
            options.map((item) => {
              const {id} = item;
              return <option value={id}>{id}</option>;
            })
          }
        </select>
      </label>
    );
}

function Field() {
  const [catIndex, setCatIndex] = useState(0);
  const [subIndex, setSubIndex] = useState(0);
  
  return (
      <div>
        <Select name='Category' options={categories} onIndex={setCatIndex}/>
        <Select name='Sub Category' options={categories[catIndex].data} onIndex={setSubIndex}/>
        <Select name='Option' options={categories[catIndex].data[subIndex].data}/>
      </div>
    );
}

function App() {
  const [fields, setFields] = useState(() => [<Field />]);
  
  const addField = useCallback(() => {
    setFields((prevFields) => {
      const index = prevFields.lenght;
      return [...prevFields, <Field key={index} />];
    });
  }, []);
  
  return (
      <Fragment>
        <form>
          {fields}
        </form>
        <button type='button' onClick={addField}>Add Field</button>
      </Fragment>
    );
}

ReactDOM.render(<App />, document.getElementById('root'));
form {
  display: flex;
  flex-direction: column;
}
<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>

如果您有任何疑问,请告诉我。

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 2020-10-09
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多