React MUI Autocomplete如何通过Props动态传递选项绑定字段
实现方案
核心问题是你传入的name属性没有被自定义组件内部逻辑消费,且硬编码的字段取值逻辑没有做动态替换,按以下两步修改即可实现多数据源复用:
1. 修改CustomAutoComplete组件
把硬编码的字段、标签全部改为从Props读取,同时兼容freeSolo模式下手动输入字符串的边界场景,避免取值报错:
import Autocomplete from "@mui/material/Autocomplete"; import Box from "@mui/material/Box"; import Stack from "@mui/material/Stack"; import TextField from "@mui/material/TextField"; export default function CustomAutoComplete(props) { // 从Props解构配置项,optionKeyField默认取id const { inputValue, set, data, optionLabelField, // 动态传入的绑定字段名,必填 label, // 输入框标签,必填 optionKeyField = "id", id = "custom-combobox" } = props; return ( <Stack sx={{ m: 1 }}> <Autocomplete sx={{ ml: 2, mr: 2 }} size="small" id={id} freeSolo inputValue={inputValue} onInputChange={(event, newValue) => { set(newValue); }} // 动态取对应字段的显示值,兼容字符串输入场景 getOptionLabel={(option) => { if (typeof option === "string") return option; return option[optionLabelField] ?? ""; }} options={data} // 动态判断值相等,兼容字符串输入场景 isOptionEqualToValue={(option, value) => { if (typeof value === "string") { return option[optionLabelField] === value; } return option[optionLabelField] === value[optionLabelField]; }} // 动态渲染选项内容和key renderOption={(liProps, option) => ( <Box component="li" {...liProps} key={option[optionKeyField]}> {option[optionLabelField]} </Box> )} renderInput={(params) => <TextField {...params} label={label} />} </Autocomplete> </Stack> ); }
2. 修改父组件调用方式
你之前写的name={region_name}有两个问题:一是region_name是未定义的变量,字符串常量需要加引号;二是组件本身没读取name属性做逻辑处理。调用时传入我们新增的配置Props即可:
import CustomAutoComplete from "../../atoms/AutoComplete"; import FormGroup from "@mui/material/FormGroup"; import { Fragment, useState, useEffect } from "react"; import { useLocalStorage } from "../../utils/LocalStorage.js"; const EventDetails = () => { const [region, setRegion] = useLocalStorage("region", ""); const [regionList, setRegionList] = useState([]); // 拉取后端区域数据 useEffect(() => { fetch("/authentication/region") .then((response) => response.json()) .then((res) => setRegionList(res)); }, []); return ( <Fragment> <FormGroup sx={{ p: 2, m: 1 }}> <CustomAutoComplete inputValue={region} set={setRegion} data={regionList} // 传入绑定的字段名和标签 optionLabelField="region_name" label="Region" /> {/* 后续如果要适配其他数据源,直接传对应字段即可,比如用户列表: <CustomAutoComplete inputValue={user} set={setUser} data={userList} optionLabelField="user_name" label="负责人" /> */} </FormGroup> </Fragment> ); };
注意点
- 所有动态字段取值都用JS对象的方括号语法
obj[fieldName]实现,不要用点语法obj.fieldName,点语法无法读取动态变量对应的属性 - 因为开启了
freeSolo属性,用户可以手动输入不在选项列表里的内容,这时候返回的value是字符串类型,必须加类型判断,否则读取value[optionLabelField]会直接报错 - 原来硬编码的组件id、输入框label都改成可配置项,避免同一页面引入多个组件时出现id重复、标签固定的问题
内容的提问来源于stack exchange,提问作者euføeni
相关产品推荐
相关产品推荐

