MaterialUI选择器设置的值始终超出范围。

74

我有一个使用MaterialUI的Select组件的代码,并且我正在动态地处理value参数。我的问题是,当我设置任何值时,它总是说它超出了范围,即使它显示在有效值中。

SelectInput.js:291 Material-UI: you have provided an out-of-range value `100001,250000` for the select (name="followers") component.
Consider providing a value that matches one of the available options or ''.
The available values are `0,50000`, `50001,100000`, `100001,250000`, `250001,500000`, `500001,750000`, `750001,9007199254740991`.
(anonymous) @ SelectInput.js:291

这是我的简化代码:

const followers = [
  { '0-50k': [0, 50000] },
  { '50k-100k': [50001, 100000] },
  { '100k-250k': [100001, 250000] },
  { '250k-500k': [250001, 500000] },
  { '500k-750k': [500001, 750000] },
  { '+1M': [750001, Number.MAX_SAFE_INTEGER] },
];

    <div className={classes.formGroup}>
                      <InputLabel id="followersL">Followers</InputLabel>
                      <Select
                        className={classes.field}
                        fullWidth
                        id="followers"
                        labelId="followersL"
                        margin="dense"
                        displayEmpty
                        name="followers"
                        onChange={(event) => setValue(event.target.value)} //I've updated the sate with the new value
                        value={
                          filters.basicInfo.followers
                            ? value 
                            : ''
                        }
                        variant="outlined"
                      >
                        {followers.map((element) => (
                          <MenuItem
                            value={element[Object.keys(element)]}
                            key={Object.keys(element)[0]}
                          >
                            {Object.keys(element)[0]}
                          </MenuItem>
                        ))}
                      </Select>
                    </div>

正如您在消息中看到的,所选值100001,250000位于范围示例100001,250000内。

问题出在哪里?


3
请检查您的componentDidMount方法。对我来说问题在于我正在更新状态,但是用于选择列表的列表为空,并且只有在后续才会填充。 - Yuri Cardoso
2
我的问题是在 Select 组件中没有包含 defaultValue。添加 defaultValue={""} 就可以了。 - notmynamelastname
9个回答

85
将 defaultValue="" 添加到下拉选择框中,例如:

1
这解决了我的警告:“Material-UI:您为选择器(name =“ stateForm”)组件提供了一个超出范围的值undefined。”谢谢。 - moonbyt3
1
这是正确的!这是MaterialUI GitHub解决了这个警告的链接:https://github.com/mui-org/material-ui/issues/18494 - lortschi
当我在字段值=undefined_variable中包含未定义的变量时,我遇到了同样的问题。 - Fernando Tholl
1
这么简单的一行代码,谢谢啊!!! - Rishi Bhachu
1
我在<Skeleton>中创建了一个新的<Select />组件,这是下拉菜单,我必须添加defaultValue =“”属性。谢谢! - cristian.nieto.dev
这是如何工作的? - johan

35

这条建议可能对其他人有用: 如果选择元素的值是对象,那么它应该是选项列表中对象的确切实例。 例如:

这个建议可能对其他人有帮助:如果 Select 元素的值是一个对象,那么它应该在选项列表中确切地匹配一个对象实例。例如:

const [test, setTest] = useState("");

//list of options for Material UI select
const testOptions = [
    {name: "123"},
    {name: "456"},
    {name: "769"},
];

//let's try to change value to {name: "123"} using JS
setTest(testOptions[0]);    // everything is OK
setTest({name: "123"});     // Error! You provided out of range value!

8
这是对这个问题的真实诊断。上面的回答告诉你将对象转为字符串只是一种解决方法。感谢分享! - gutscdav000
5
我开始变得有点疯狂了!感谢! 对于其他面临这个问题的人:不要在组件内创建列表。我也遇到过同样的问题,原因就在于此。应该在组件函数之外创建列表,例如在其上方(如果您正在使用函数式组件)。 - Amin Dannak
非常感谢!对于我来说,所有选项都是从API(getServerSideProps)动态获取的,并且在每次Next.js编程式导航时,我都添加了一个useEffect,以便从新数组中再次设置所选选项。 - Harry Theo

6
将您的值字符串化将使其正常工作。
element[Object.keys(element)] + ""}

如果您需要在将结果发送到服务器之前将其恢复为原始数组格式,您可以使用类似以下的函数来完成此操作。
const strToArr = str => str.split(',').map(item => Number(item)) 

在我的代码中,我使用了您提供的示例并成功地复制了您的错误。但是将该值转为字符串可以消除错误并使其按预期工作。

    
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import Select from "@material-ui/core/Select";

const useStyles = makeStyles(theme => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120
  },
  selectEmpty: {
    marginTop: theme.spacing(2)
  }
}));

export default function SimpleSelect() {
  const classes = useStyles();

  const followers = [
    { "0-50k": [0, 50000] },
    { "50k-100k": [50001, 100000] },
    { "100k-250k": [100001, 250000] },
    { "250k-500k": [250001, 500000] },
    { "500k-750k": [500001, 750000] },
    { "+1M": [750001, Number.MAX_SAFE_INTEGER] }
  ];
  const [value, setValue] = React.useState("");
  const handleChange = event => setValue(event.target.value);

  return (
    <div>
      <p>value - {value}</p>
      <div className={classes.formGroup}>
        <InputLabel id="followersL">Followers</InputLabel>
        <Select
          className={classes.field}
          fullWidth
          id="followers"
          labelId="followersL"
          margin="dense"
          displayEmpty
          name="followers"
          onChange={handleChange}
          value={value}
          variant="outlined"
        >
          {followers.map(element => (
            <MenuItem
              value={element[Object.keys(element)] + ""}
              key={Object.keys(element)[0]}
            >
              {Object.keys(element)[0]}
            </MenuItem>
          ))}
        </Select>
      </div>
    </div>
  );
}


3

当我使用默认值为-1number状态时,我遇到了和你提供的数值超出范围的问题:

const [selectedAccountId, setSelectedAccountId] = useState<number>(-1);

解决该问题的方法是在Material UI的

2

根据一些研究,我理解在我的情况下出现这个警告的原因是MUI Select尝试映射一个列表的选项,但是这些选项在第一次渲染时并不可用,因为列表是从Axios响应中获取的。

我创建了一个名为Dropdown的组件来呈现MUI Select组件。我提供了四个属性:

  1. options:选项列表,
  2. initialValue:默认值,因为Dropdown组件的不同实例具有不同的默认值,而且这些默认值通常不是options列表的第一项

其他两个属性与本讨论无关。

因此,对于Dropdown组件的每个实例,我必须检查options列表是否有任何数据,只有在有数据时才渲染组件。这就消除了控制台中的警告。以下是我所做的事情的简要概述:

{viewsData.length > 0 && (
  <Dropdown
    options={viewsData}
    initialValue={7}
    {...otherProps}
  />
 )}

这个问题困扰了我很长时间,希望能对某些人有所帮助。


这正是我的问题。谢谢你分享这个!我以类似的方式解决了它。首先检查选项集合是否为空。如果是,就用一些临时的初始值来设置它。 - undefined

1
这是因为在加载options之前,value应该是'',然后通常是一个对象数组。
修复这个问题最简洁的方法是在您的MUI <Select>中添加prop:
  • 对于受控组件:value={options.length > 0 ? value : ''}
  • 对于非受控组件:value={options.length > 0 ? field.value : ''},其中field.value例如来自react-hook-form中的<Controller render={({ field }) => ( ...包装MUI <Select>

0

补充 @Ait Friha Zaid 的回答。

我也添加了 defaultValue 属性,但还增加了一个额外的选项:

const values = ['option 1', 'option 2', 'option 3'];

 <FormControl fullWidth>
  <InputLabel>{title}</InputLabel>
    <Select 
      defaultValue="choose"
      label={title} 
      onChange={e => func({...state, [keyName]: e.target.value}) }
    >
      <MenuItem disabled value="choose">Choose Option</MenuItem>
      {values.map((value) => (
        <MenuItem value={value} key={value}>{value}</MenuItem>
      ))}
  </Select>
</FormControl>

这样,您始终拥有一个禁用的选项作为占位符,这是默认选项。如果您想进行表单验证,在用户更改选项之前,状态不会更改。


0
我需要采用另一种方法,因为上述的解决方案都对我无效。
我不得不将数组的第一个元素设置为实际值,作为默认值。换句话说,我将第一个元素设为'',但实际上应该是' '。然后,将默认值设置为array[0],其中array[0] = ' ',这样就可以从第一个元素开始使用了。

0

我遇到了同样的错误,通过确保默认值和其后的其他选择值相同来解决它,例如,如果默认值是像''这样的字符串,则其他值为objects,它将显示警告,因此为了避免这样的问题,请将默认值设置为[]{}或最好是null


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接