动态生成的 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>
如有任何疑问,请告诉我。
我有一个 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>
如有任何疑问,请告诉我。