动态生成的 React 控制输入

Dynamically Generated React Controlled Inputs

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

我正在将 selected 值存储为对象数组,例如

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

示例数据:

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

]

所以从字面上看,第一组输入可以用 exerciseData[0] 表示,下一个可以用 exerciseData[1].category 等表示。

问题是我希望用户重新排序组,例如向上移动 1 组或向下移动 1.So 我需要 select 框作为受控元素。但是我该如何设置呢?

我这样试过:

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

当我这样给出时 select 框值不能 changed.it 始终保持其默认值。

如有任何建议,我们将不胜感激 提前致谢

要使输入受控,您需要通过状态手动处理输入值。在您的示例中,输入值似乎是 fixed/static.

以下代码段是如何在 React 中创建受控 select 输入的示例。

更新:

制作了完整的演示片段。如果这就是您要找的,请告诉我。

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>

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