React 使用 Material-UI 创建动态选择和选项元素

Jim*_*Jim 3 javascript reactjs material-ui dropdown react-hooks

所以,老实说,我以为这需要 15 分钟,但我现在大约需要 5 个小时。让我如此困扰的是,我知道这是一个简单的解决方案,而且我也尝试了几种不同的方法。

我有一个 React 应用程序,在诊断组件内,有两个下拉元素,允许用户选择其设备的品牌和型号。我想做的是允许用户选择他们拥有的品牌,当选择品牌下拉列表时,模型下拉列表会自动填充。

这是我的 MakeandModel.js 文件:

import React, { useState, useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';
import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem';

import makeandmodel_DATA from './makeandmodel_DATA';

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

console.log(makeandmodel_DATA);

export default () => {
    const classes = useStyles();
    const [data, setData] = useState();
    const [make, setMake] = useState('');
    const [model, setModel] = useState('');

    useEffect(() => {
        
    });

    const handleMakeChange = (event) => (
        setMake(event.target.value)
    );

    const handleModelChange = (event) => (
        setModel(event.target.value)
    );

    return (
        <>
            <FormControl variant="outlined" className={classes.formControl}>
                <InputLabel id="demo-simple-select-outlined-label">Make</InputLabel>
                <Select
                    labelId="demo-simple-select-outlined-label"
                    id="demo-simple-select-outlined"
                    value={make}
                    onChange={handleMakeChange}
                    label="Make"
                >
                    <MenuItem value="">
                        <em>Choose a Make</em>
                    </MenuItem>
                    {makeandmodel_DATA.map((make, index) => (
                        <MenuItem key={index} value={make.name}>{make.name}</MenuItem>
                    ))}
                </Select>
            </FormControl>

            <FormControl variant="outlined" className={classes.formControl}>
                <InputLabel id="demo-simple-select-outlined-label">Model</InputLabel>
                <Select
                    labelId="demo-simple-select-outlined-label"
                    id="demo-simple-select-outlined"
                    value={model}
                    onChange={handleModelChange}
                    label="Model"
                >
                    <MenuItem value="">
                        <em>Choose a Model</em>
                    </MenuItem>
                    
                </Select>
            </FormControl>
            <br />
       </>
    );
};
Run Code Online (Sandbox Code Playgroud)

我还有一些正在导入的示例数据,以尝试填充我的“品牌”和“型号”下拉列表。以下是 makeandmodel_DATA.json 文件中的代码:

[
    {
        "name": "Dyson",
        "models": [
            {
                "name": "v12"
            },
            {
                "name": "v10"
            },
            {
                "name": "ball"
            }
        ]
    },
    {
        "name": "Oreck",
        "models": [
            {
                "name": "Upright"
            },
            {
                "name": "Unique"
            },
            {
                "name": "XL"
            }
        ]
    },
    {
        "name": "Electrolux",
        "models": [
            {
                "name": "Classic"
            },
            {
                "name": "Vintage"
            },
            {
                "name": "New School"
            }
        ]
    },
    {
        "name": "Kirby",
        "models": [
            {
                "name": "Heavy"
            },
            {
                "name": "Light"
            },
            {
                "name": "Regular"
            }
        ]
    },
    {
        "name": "Hoover",
        "models": [
            {
                "name": "Windtunnel"
            },
            {
                "name": "Back"
            },
            {
                "name": "Upright"
            }
        ]
    }
]
Run Code Online (Sandbox Code Playgroud)

我尝试映射导入的数据,但每次我这样做来查找模型时,最终都会返回未定义的结果。

我还尝试连接 useEffect 函数,但也无法弄清楚如何正确连接它。

就像我说的,我觉得解决方案非常简单,但我忽略了一些基本的东西。我真的只是在寻找一个超级简单的解决方案,看起来干净而且效果很好。如果您需要任何其他信息来帮助我们解决此问题,请尽管询问。

提前致谢!

小智 6

这里的最佳实践是创建一个对象,您可以在其中按名称保存模型Make

const models = React.useMemo(() => {
  const modelsValues = {};
  makeandmodel_DATA.forEach(({ name, models }) => {
    modelsValues[name] = models;
  })

 return modelsValues;
})
Run Code Online (Sandbox Code Playgroud)

您只需在执行此操作时保存模型名称即可。然后你需要访问选定的Make模型,最后你的Make选择将是这样的:

         {make && <FormControl variant="outlined" className={classes.formControl}>
            <InputLabel id="demo-simple-select-outlined-label">Model</InputLabel>
            <Select
                labelId="demo-simple-select-outlined-label"
                id="demo-simple-select-outlined"
                value={model}
                onChange={handleModelChange}
                label="Model"
            >
                <MenuItem value="">
                    <em>Choose a Model</em>
                </MenuItem>
              {models[make] ? models[make].map(model=> {
                // Here goes your models option
                return <MenuItem value="">
                    <em>Choose a Model</em>
                </MenuItem>
                }) : null
               }
            </Select>
        </FormControl>}
Run Code Online (Sandbox Code Playgroud)

也许我有一个拼写错误,但如果你能给我一个沙箱,修复起来会更容易。


Jim*_*Jim 5

这是一个很好的解决方案!

我做了同样的事情,我向映射函数添加了一个索引,以向每个 MenuItem 添加一个键,并将每个 MenuItem 上的 value 属性和子项设置为 model.name

{make && <FormControl variant="outlined" className={classes.formControl}>
         <InputLabel id="demo-simple-select-outlined-label">Model</InputLabel>
         <Select
             labelId="demo-simple-select-outlined-label"
             id="demo-simple-select-outlined"
             value={model}
             onChange={handleModelChange}
             label="Model"
         >
             <MenuItem value="">
                 <em>Choose a Model</em>
             </MenuItem>
             {models[make] 
                 ? models[make].map((model, index) => (
                     <MenuItem key={index} value={model.name}>{model.name}</MenuItem>
                 ))
                 : null
             }
    

     </Select>
</FormControl>}
Run Code Online (Sandbox Code Playgroud)