材质 UI 选择不显示标签

low*_*ler 5 javascript reactjs material-ui

我在 Material UI 的“选择”上玩得很开心 - 大约 10 个小时试图让一个人以我想要的方式工作。我真的很感激一些帮助。

这个问题与前一个问题有关:Select MenuItem 不显示 JSX 保存到状态的时间,我怀疑如果“为什么”得到了回答,我可能会更好地了解发生了什么。

我想要完成的是让 Select 执行以下正常操作:

  • 拥有所有 UI 好东西(在选择位置显示问题,然后在选择非空选择后将问题移小并移开)
  • 选择某些内容后,标签会显示(正如人们在下拉列表中所期望的那样)而不是空白(正如我所经历的 - 检查上一个问题)
  • 控制台中没有关于“值”未定义的警告
  • 当我在选择某些内容后单击远离选择时,我不希望问题标签像这样移回到答案的顶部: 选定的选项和问题标签在彼此之上
  • 我想要一个“无”选项,将选择返回到它的“空”形式(也就是说,问题标签在选择中以正常大小显示)
  • 我可以设置一个选择以默认选择

这些不应该是艰巨的任务,但我一辈子都做不到。比较尴尬

  • 然后,在选择某些内容时,我想将该选择(以及其他选择选项)保存到状态(以便我可以将其保存到 localStorage 以便较大的表单不会在页面刷新时“重置”)

无论哪种方式,我目前都有这个 JSX - 有效地从材料 ui 演示中剪切和粘贴,并带有以下地图MenuItems

<FormControl className={classes.formControl}>
<InputLabel htmlFor={this.props.label}>{this.props.label}</InputLabel>
<Select
    value={this.state.selectLabel}
    onChange={this.handleSelectChange}
    inputProps={{
        name: 'selectLabel',  
        id: this.props.label,
    }}
>
{this.props.value.map(valueLabelPair =>
                <MenuItem
                    key={this.props.XMLvalue + "_" + valueLabelPair.label}
                    value={valueLabelPair.value}
                >
                    {valueLabelPair.label}
                </MenuItem>
            )}
</Select>
</FormControl>
Run Code Online (Sandbox Code Playgroud)

handleSelectChange 看起来像这样——同样,与材质 UI 演示完全相同。

handleSelectChange = event => {
    this.setState({ [event.target.name]: event.target.value });
};
Run Code Online (Sandbox Code Playgroud)

这种工作除了控制台给我以下错误:

失败的道具类型:道具value在 中标记为必需 SelectInput,但其值为undefined

单击离开后,所选选项和问题标签会重叠在一起,如下所示: 选定的选项和问题标签在彼此之上

此外,如果我尝试添加此代码(在 componentDidMount 函数中),目标是能够传入“selected”/默认选项......

componentDidMount() {
    for (var i = 0; i < this.props.value.length; i++) {
        if(this.props.value[i].selected) {
            // *works* console.log("selected found: " + this.props.value[i].label);
            this.setState({selectLabel:this.props.value[i].label});
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它不会更新给我一个默认答案,并且还会在控制台中给我以下附加错误(除了上述所有问题):

警告:组件正在将隐藏类型的不受控制的输入更改为受控制。输入元素不应从不受控制切换到受控制(反之亦然)。决定在组件的生命周期内使用受控或非受控输入元素。

我错过了什么?

low*_*ler 0

我不确定为什么上述解决方案不起作用。

但是,我使用以下函数重建了 Select 以返回“option”元素而不是“MenuItem”元素:

buildSelectOptions(optionsPairs) {  // note, this references props and blank option could be split out for reuse
    var JSX_return = [];

    if (this.props.includeBlank && this.props.includeBlank === true) {
        JSX_return.push(<option key="nada" value="" />);
    }

    for (var optionLabel in optionsPairs) {
        JSX_return.push(<option key={optionLabel} value={optionsPairs[optionLabel]}>{optionLabel}</option>);
    }
    return JSX_return;
}
Run Code Online (Sandbox Code Playgroud)

我的渲染现在看起来像这样:

<FormControl className={classes.formControl}>
    <InputLabel htmlFor="age-native-simple">{this.props.label}</InputLabel>
    <Select
        native
        value={this.state.value}
        onChange={this.handleSelectChange('value')}
        inputProps={{
            name: this.props.label,
            id: this.props.id,
          }}
    >
        {this.buildSelectOptions(this.props.options)}

    </Select>
    <FormHelperText>{this.props.helperText}</FormHelperText>
</FormControl>
Run Code Online (Sandbox Code Playgroud)

事件处理程序如下所示:

handleSelectChange = name => event => {  //FUTURE: combine the handlers  (or split out question types to sub-components)
    this.setState({ [name]: event.target.value },
        () => this.props.stateChangeHandler(this)
    );
};
Run Code Online (Sandbox Code Playgroud)

传递给该对象的 props 如下所示:

{
    "key": "test4",
    "id": "test4",
    "label": "Question Label 4",
    "XMLValue": "XMLQ4",
    "type": "DropDown",
    "includeBlank": true,
    "helperText": "PCodes FTW!",
    "options": {
        "No oe": "NA",
        "My1": "One",
        "My2": "Two",
        "My3": "three"
    },
    "value": "One"
}
Run Code Online (Sandbox Code Playgroud)

对我来说,关键概念之一是了解元素value上的字段Select应该指向this.state. 然后,onChange 需要将该状态变量的名称(令人困惑的是,我将其命名为“value”)传递给 eventHandler 函数。

handleSelectChange函数的双箭头函数头(柯里化函数)仍然让我感到困惑...(我不明白“事件”属性是如何到达那里的,因为我使用单个参数调用这个函数)...但是这目前有效,我可以尝试function(a, b) { *do something* }在将来的某个日期重构为我熟悉的语法(即:)。(是的....)