我无法让 select 使用新的子组件填充组件并保留其值
I can't make select populate component with new child components and retain its value
好吧,复杂的。我会尽可能简单。
我正在构建一个应用程序来创建 json 查询,然后将其发送到服务器。
构建查询的组件采用嵌套结构:QueryContainer > QueryGroup > QueryRow > 一系列表单组件:QueryRowSelectField(用于制作 selection 的下拉菜单)、QueryRowDateInput、QueryRowPackageTypeInput、 QueryRowPackageSizeInput.
想法是您有 'groups' 个查询,每个查询都包含 'rows',因此一个查询组可能包含三行,其中一行将用户规定为 'Dave',另一行声明请求的 packageType,另一个给出数据范围。
每次添加、删除或更改组或行时,它都会在名为 'query' 的上下文中更新一个对象,然后,这又会用于填充前端,以便用户可以看到他们正在构建的查询。
这似乎一切正常。我最终保留了 'root' QueryContainer 组件中的大部分功能,并使用 props 将其传递给 QueryGroup、QueryRow 和 QueryRow 组件。
虽然我 运行 遇到了一个问题,但无法解决。
我不知道如何在 QueryRowSelectField 中保留 selected 值。
select下拉菜单的代码如下:
<select
value={selectFieldState}
name='field'
onChange={(e) => {
handleChange(e, changeFieldInRow, groupIndex, rowIndex);
}}
className='form-control form-control-sm'
>
{populateSelectField()}
</select>
这反过来又调用一个句柄更改函数,将事件传递给它,该函数根据 selection (changeFieldInRow)、查询中组的索引和查询中两者的索引。最后三个是从QueryContainer传下来的。
handleChange如下:
const handleChange = (e, changeFieldInRow, groupIndex, rowIndex) => {
let selectedValue = e.currentTarget.value;
updateFieldsInGroup(groupIndex);
changeFieldInRow(selectedValue, groupIndex, rowIndex);
setSelectFieldState(selectedValue);
};
select 选项存储为包含本地状态标签和值的对象数组。
updateFieldsInGroup 基本上过滤掉当前 selected 的下拉选项,以便在启动下一行时它不会出现在选项中。
最重要的是,selected 选项被发送到 selectFieldState,然后用于填充 select.
中的值属性
如上所述,select 下拉列表在更改后不会保留其显示的值。其他一切似乎工作正常。如果我删除函数调用 'changeFieldInRow(selectedValue, groupIndex, rowIndex)',则该值会保留,但在生成 selection 时,行组件不会改变。
如果我在 handleChange 中使用字符串设置 selectFieldState,例如setSelectFieldState('user');然后它保留该字符串值,但如果我尝试使用状态值,尽管它显示在控制台的查询中,它只是 returns 默认值。
因此问题与 changeFieldInRow 有关。我怀疑当它重新呈现时它会删除现有值,因此不会保留任何内容,但在那种情况下它应该会删除硬编码的 setSelectFieldState('user');它没有。
我坚持这个所以如果有人能指出我正确的方向那么我将不胜感激。
如果以上内容不清楚,可以在以下位置找到文件:https://github.com/stefemil1969/queryMaker
当前 'working' 示例可在此处找到:https://codesandbox.io/s/youthful-mendeleev-7wzs2?file=/public/index.html
3 点要指出:
通过event.target.value
而不是event.currentTarget.value
获取select
的值
由于您使用的是受控 select
组件,每次它发生变化时,您都需要使用 useState
:[=20 提供的函数将这种变化反映到您的本地状态=]
const handleChange = (e, changeFieldInRow, groupIndex, rowIndex) => {
let selectedValue = e.target.value;
setSelectFieldState(selectedValue); <- reflect the change to local state
updateFieldsInGroup(groupIndex);
changeFieldInRow(selectedValue, groupIndex, rowIndex);
setSelectFieldState(selectedValue);
};
您需要将选定的字段包含到将要填充的字段中,这样 select
组件才能正确显示其标签
我注意到您没有正确使用 map
函数,请从代码沙盒中查找这些警告。在这些情况下,我想你会想使用 forEach
来代替。
好吧,复杂的。我会尽可能简单。
我正在构建一个应用程序来创建 json 查询,然后将其发送到服务器。
构建查询的组件采用嵌套结构:QueryContainer > QueryGroup > QueryRow > 一系列表单组件:QueryRowSelectField(用于制作 selection 的下拉菜单)、QueryRowDateInput、QueryRowPackageTypeInput、 QueryRowPackageSizeInput.
想法是您有 'groups' 个查询,每个查询都包含 'rows',因此一个查询组可能包含三行,其中一行将用户规定为 'Dave',另一行声明请求的 packageType,另一个给出数据范围。
每次添加、删除或更改组或行时,它都会在名为 'query' 的上下文中更新一个对象,然后,这又会用于填充前端,以便用户可以看到他们正在构建的查询。
这似乎一切正常。我最终保留了 'root' QueryContainer 组件中的大部分功能,并使用 props 将其传递给 QueryGroup、QueryRow 和 QueryRow 组件。
虽然我 运行 遇到了一个问题,但无法解决。
我不知道如何在 QueryRowSelectField 中保留 selected 值。
select下拉菜单的代码如下:
<select
value={selectFieldState}
name='field'
onChange={(e) => {
handleChange(e, changeFieldInRow, groupIndex, rowIndex);
}}
className='form-control form-control-sm'
>
{populateSelectField()}
</select>
这反过来又调用一个句柄更改函数,将事件传递给它,该函数根据 selection (changeFieldInRow)、查询中组的索引和查询中两者的索引。最后三个是从QueryContainer传下来的。
handleChange如下:
const handleChange = (e, changeFieldInRow, groupIndex, rowIndex) => {
let selectedValue = e.currentTarget.value;
updateFieldsInGroup(groupIndex);
changeFieldInRow(selectedValue, groupIndex, rowIndex);
setSelectFieldState(selectedValue);
};
select 选项存储为包含本地状态标签和值的对象数组。 updateFieldsInGroup 基本上过滤掉当前 selected 的下拉选项,以便在启动下一行时它不会出现在选项中。
最重要的是,selected 选项被发送到 selectFieldState,然后用于填充 select.
中的值属性如上所述,select 下拉列表在更改后不会保留其显示的值。其他一切似乎工作正常。如果我删除函数调用 'changeFieldInRow(selectedValue, groupIndex, rowIndex)',则该值会保留,但在生成 selection 时,行组件不会改变。
如果我在 handleChange 中使用字符串设置 selectFieldState,例如setSelectFieldState('user');然后它保留该字符串值,但如果我尝试使用状态值,尽管它显示在控制台的查询中,它只是 returns 默认值。
因此问题与 changeFieldInRow 有关。我怀疑当它重新呈现时它会删除现有值,因此不会保留任何内容,但在那种情况下它应该会删除硬编码的 setSelectFieldState('user');它没有。
我坚持这个所以如果有人能指出我正确的方向那么我将不胜感激。
如果以上内容不清楚,可以在以下位置找到文件:https://github.com/stefemil1969/queryMaker
当前 'working' 示例可在此处找到:https://codesandbox.io/s/youthful-mendeleev-7wzs2?file=/public/index.html
3 点要指出:
通过
获取event.target.value
而不是event.currentTarget.value
select
的值由于您使用的是受控
select
组件,每次它发生变化时,您都需要使用useState
:[=20 提供的函数将这种变化反映到您的本地状态=]const handleChange = (e, changeFieldInRow, groupIndex, rowIndex) => { let selectedValue = e.target.value; setSelectFieldState(selectedValue); <- reflect the change to local state updateFieldsInGroup(groupIndex); changeFieldInRow(selectedValue, groupIndex, rowIndex); setSelectFieldState(selectedValue); };
您需要将选定的字段包含到将要填充的字段中,这样
select
组件才能正确显示其标签
我注意到您没有正确使用 map
函数,请从代码沙盒中查找这些警告。在这些情况下,我想你会想使用 forEach
来代替。