我无法让 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 点要指出:

  1. 通过event.target.value而不是event.currentTarget.value

    获取select的值
  2. 由于您使用的是受控 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);
    };
    
  3. 您需要将选定的字段包含到将要填充的字段中,这样 select 组件才能正确显示其标签

这是工作演示:https://codesandbox.io/s/modern-architecture-oyf0e?file=/src/components/query/queryRow/queryRowComponents/QueryRowSelectField.js:1838-2129

我注意到您没有正确使用 map 函数,请从代码沙盒中查找这些警告。在这些情况下,我想你会想使用 forEach 来代替。