简体   繁体   English

MUI Object in Select默认值不显示但选择object时显示

[英]MUI Object in Select default value not showing but shows when object selected

As the code shows options has a "chosenValue" by default, however I have to change it for something to show by default in the dropdown or the dropdown is empty.由于代码显示选项默认有一个“chosenValue”,但是我必须更改它以在下拉列表中默认显示某些内容或下拉列表为空。 How can I make it so when the page loads it by default value show "chosenValue"?当页面以默认值加载时如何显示“chosenValue”? Here is a codesandbok example: https://codesandbox.io/s/practical-noether-dwt52t?file=/src/App.js:0-1421这是一个codesandbok示例: https://codesandbox.io/s/practical-noether-dwt52t?file=/src/App.js:0-1421

import "./styles.css";
import {
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  OutlinedInput
} from "@mui/material";
import { useState } from "react";
export default function App() {
  const [options, setOptions] = useState({
    chosenValue: {
      label: "apple",
      color: "green"
    },
    aviableValues: [
      { label: "apple", color: "red" },
      { label: "Orange", color: "Orange" },
      { label: "pear", color: "green" }
    ]
  });
  const handleContentChange = (event) => {
    setOptions((prevState) => ({
      ...prevState,
      chosenValue: event.target.value
    }));
  };
  return (
    <>
      {options.chosenValue && (
        <FormControl sx={{ mt: 2 }}>
          <InputLabel id="demo-simple-select-helper-label">Fruits</InputLabel>
          <Select
            labelId="demo-simple-select-label"
            id="demo-simple-select"
            value={options.chosenValue}
            onChange={(e) => handleContentChange(e)}
            input={<OutlinedInput label={options.chosenValue.label} />}
            fullWidth
          >
            {options.aviableValues.map((item) => {
              return (
                <MenuItem value={item} key={item}>
                  {item.label}
                </MenuItem>
              );
            })}
          </Select>
        </FormControl>
      )}
      {options.chosenValue && <p>{options.chosenValue.label}</p>}
    </>
  );
}

Working example in Code Sandbox代码沙箱中的工作示例

I have forked your example in Code Sandbox and modified it with a working implementation.我已经在 Code Sandbox 中分叉了您的示例,并使用有效的实现对其进行了修改。 I have also included an Autocomplete alternative.我还包括了一个Autocomplete选项。

https://codesandbox.io/s/musing-dew-58frco https://codesandbox.io/s/musing-dew-58frco

Why selected option isn't displaying为什么选择的选项不显示

As Ivan has stated, the reason why your Select component isn't showing the selected value is because the selected value is a different object than the value in the options and the Select component requires that the objects are strictly equal ( === ).正如 Ivan 所说,您的Select组件未显示所选值的原因是因为所选值与选项中的值不同, object 并且Select组件要求对象严格相等( === )。

For example, although these objects appear to be the same, they will fail the strict equality check.例如,尽管这些对象看起来相同,但它们将无法通过严格的相等性检查。 You can test this example in your console, which will result in false .您可以在控制台中测试此示例,这将导致false

{ fruit: "apple" } === { fruit: "apple" } 

How to use Select Select使用方法

The easiest way to use Select is for your value to be a string and your options to each have a label and value key (both strings).使用Select的最简单方法是让您的值成为一个字符串,并且您的每个选项都有一个 label 和值键(两个字符串)。 The label is what will be displayed on the screen and the value is what will be selected when the option is chosen. label 是将显示在屏幕上的内容,值是选择选项时将选择的内容。

For example, for your options, you could have:例如,对于您的选择,您可以:

const options = [
  { label: "Apple", color: "red", value: "apple" },
  { label: "Orange", color: "orange", value: "orange" },
  { label: "Pear", color: "green", value: "pear" }
];

Instead of storing your options in state, you could have it as a variable outside of state since it is not changing.与其将选项存储在 state 中,不如将其作为 state 之外的变量,因为它不会改变。

You only need to keep state for the selected value, which I'll call fruit .您只需要保留 state 作为所选值,我将其称为fruit apple is the initial value of fruit. apple是水果的初始值。

const [fruit, setFruit] = useState("apple");

In your Select component, assign fruit to the value prop and ensure that the value of each item is provided to the value prop of MenuItem :在您的Select组件中,将fruit分配给value prop 并确保每个项目的value都提供给MenuItemvalue prop:

<Select
  labelId="demo-simple-select-label"
  id="demo-simple-select"
  value={fruit} // this is coming from state
  onChange={(e) => setFruit(e.target.value)} // we can setFruit directly here
  input={<OutlinedInput label="Hello" />}
  fullWidth
>
  {options.map((item) => {
    return (
      <MenuItem value={item.value} key={item.value}>
        {item.label}
      </MenuItem>
    );
  })}
</Select>

Instead of having a separate handleChange function, we can setFruit directly within the onChange prop.我们可以直接在onChange道具中设置水果,而不是单独的 handleChange function。

The defaultValue is not required and should only be used if the component is not controlled. defaultValue不是必需的,只有在组件不受控制时才应使用。 This is from the Material UI docs :这是来自Material UI 文档

The default value.默认值。 Use when the component is not controlled.当组件不受控制时使用。

Ours is a controlled component since we are providing value from state (fruit) and also handling the change (setFruit).我们的组件是一个受控组件,因为我们提供 state(水果)的值并处理更改 (setFruit)。

Alternative is to use Autocomplete - if you wanted the selected item as an object替代方法是使用自动完成 - 如果您希望将所选项目作为 object

In the explanation above, I am using string values ie apple , orange and pear .在上面的解释中,我使用的是字符串值,即appleorangepear If you wanted your selected values to be objects instead, eg { label: "Apple", color: "red", value: "apple" } , then you can use Material UI's Autocomplete .如果您希望选择的值改为对象,例如{ label: "Apple", color: "red", value: "apple" } ,那么您可以使用Material UI 的 Autocomplete

We have the same options:我们有相同的选择:

const options = [
  { label: "Apple", color: "red", value: "apple" },
  { label: "Orange", color: "orange", value: "orange" },
  { label: "Pear", color: "green", value: "pear" }
];

But our state is different:但是我们的 state 不一样:

const [fruit, setFruit] = useState({
  label: "Apple",
  color: "red",
  value: "apple"
});

Note that the initial state here must match exactly with one of the options.请注意,此处的初始 state 必须与其中一个选项完全匹配。

The Autocomplete component provides an isOptionEqualToValue prop which compares the value we have selected to the options we can select from to determine which it should render. Autocomplete组件提供了一个isOptionEqualToValue道具,它将我们选择的值与我们可以 select 从中确定它应该呈现的选项进行比较。 We want to compare the value key of the selected item and the option items.我们要比较所选项目和选项项目的value键。 If they are equal, the option that matches will be displayed.如果相等,则显示匹配的选项。 For example, if the selected item is { label: "Apple", color: "red", value: "apple" } and there is an option that is also { label: "Apple", color: "red", value: "apple" } , since both their values are equal ("apple" === "apple" is true), then "Apple" will be displayed as selected.例如,如果所选项目是{ label: "Apple", color: "red", value: "apple" }并且有一个选项也是{ label: "Apple", color: "red", value: "apple" } ,因为它们的值相等("apple" === "apple" 为真),那么 "Apple" 将显示为选中状态。

Now putting it altogether with the Autocomplete component:现在将它与Autocomplete组件放在一起:

<Autocomplete
  options={options}
  value={fruit}
  isOptionEqualToValue={(option, value) => option.value === value.value}
  onChange={(event, newValue) => {
    setFruit(newValue);
  }}
  renderInput={(params) => (
    <TextField {...params} label="Fruits" variant="standard" />
  )}
/>;

Hope this helps.希望这可以帮助。

The issue you are encountering is that object comparisons only evaluate to true if you compare the same exact object. (See https://stackoverflow.com/a/11705017/18920728 )您遇到的问题是,如果您比较完全相同的 object ,则 object 比较只会评估为真。(请参阅https://stackoverflow.com/a/11705017/18920728

options.aviableValues[0] === options.chosenValue  // false

To fix this, you can tell Mui how an option object should be rendered explicitly.要解决此问题,您可以告诉 Mui 选项 object 应该如何显式呈现。

<Select
  // other props...
  renderValue={(o) => o.label}  // add this line
>

Alternatively, you can split your options state into 2 states:或者,您可以将选项 state 拆分为 2 个状态:

const [options] = useState([
  { label: "apple", color: "red" },
  { label: "Orange", color: "Orange" },
  { label: "pear", color: "green" }
]);
const [selected, setSelected] = useState(options[0]);

...

<Select
  ...
  value={selected}
  ...
>

Note that since you are controlling the select component, there is no need to specify the default prop in <Select> , the default value is already specified as the default state when useState hook is called.请注意,由于您控制的是 select 组件,因此无需在<Select>中指定default属性,默认值已在调用useState钩子时指定为默认值 state。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM