ReactJS 将未闭合的元素推送到变量

ReactJS pushing unclosed elements to a variable

我有一个表单生成器,它根据 JSON 元素生成表单元素。因为在这个过程中,我们附加了一个开放元素,JSX 抛出了一个错误。实现此目标的最佳 Reactful 方法是什么?

样本JSON:

[
    {
        "name": "1900",
        "label": "Year 1900"
    },
    {
        "name": "",
        "label": "Group 2000",
        "type": "groupstart"
    },
    {
        "name": "2000",
        "label": "Year 2000",
        "select": true
    },
    {
        "name": "2001",
        "label": "Year 2002"
    },
    {
        "name": "2002",
        "label": "Year 2002"
    },
    {
        "name": "",
        "label": "",
        "type": "groupend"
    },
    {
        "name": "2100",
        "label": "Year 2100"
    }
]

预期输出

<select>
    <option value="1900">Year 1900</option>
    <optgroup label="Group 2000">
        <option value="2000" selected>Year 2000</option>
        <option value="2001">Year 2001</option>
    </optgroup>
    <option value="2100">Year 2100</option>
</select> 

我目前的代码片段:

let fieldOptions = []
    field.options.selectOptions.map(function(entry){
      if (entry.type === 'groupstart') {
        fieldOptions.push(<optgroup label={entry.label}>)
      } else if (entry.type === 'groupend') {
        fieldOptions.push('</optgroup>');
      } else {
        fieldOptions.push(<option value={entry.name}>{entry.label}</option>)        
      }
    });
    results.push(
      <select
        name={field.name}
        ref={field.name}
        key={field.id}
        onChange={(e) => {field.onChange(e, field.entryType); }}
        onFocus={() => { focusFunction(field); }}
        value={field.value}>
          { fieldOptions }
      </select>
    );

是的,这在 React (JSX) 中是不可能的。你必须做类似

的事情
let fieldOptions = [];
let group;

for (let index = 0; index < field.options.selectOptions.length; index++) {
    let entry = field.options.selectOptions[index];

    if (!entry.type) {
        let option = <option value={ entry.name }>{ entry.label }</option>;
        if (group) group.push(option);
        else fieldOptions.push(option);
    } else if (entry.type === 'groupstart') {
        group = [];
        group.push(<option value={ entry.name }>{ entry.label }</option>);
    } else if (entry.type === 'groupend') {
        const groupStart = group[0];
        group.push(<option value={ entry.name }>{ entry.label }</option>);
        fieldOptions.push(<optgroup label={ groupStart.label }>{ group }</optgroup>);
        group = null;
    }
}

results.push(
    <select
        name={ field.name }
        ref={ field.name }
        key={ field.id }
        onChange={ (e) => { field.onChange(e, field.entryType); } }
        onFocus={ () => { focusFunction(field); } }
        value={ field.value }>
        { fieldOptions }
    </select>
);

为什么你的 JSON 持平?您应该考虑修改 JSON 架构以支持嵌套元素。

更好的模式是

[
    {
        "name": "...",
        "label": "..."
    }, 
    {
        "type": "group",
        "label": "...",
        "items": [
            {
                "name": "...",
                "label": "..."
            }
            ...
        ]
    }
]