React下拉选择框:如何获取展示数组以外的更多字段?
问题
我有一个包含ID、name和description字段的JSON数组,想做一个下拉选择框,选项里展示name和description,选中时把对应的ID存入rawID状态。现在只能通过在选项里显示ID再拆分提取的方式实现,用户体验很差,选项会显示成raw1: description1 *id number。能不能直接把ID传入点击处理函数?
原始父组件代码:
const form = () => { const [allRaws, setAllRaws] = useState([]) const [rawID, setRawsID] = useState('') setAllRaws([ {"ID" : 1, "name" : "raw1", "description" : "description 1"}, {"ID" : 2, "name" : "raw2", "description" : "description 2"}, {"ID" : 3, "name" : "raw3", "description" : "description 3"}, ]) const handleSelectRaws = (event, value) =>{ if (value != null){ const id = value.split("*").pop() setRawsID(id) } } return ( <AutocompleteForm array={allRaws.map((raw) => ([String(raw.name)]+ ": " + String(raw.description) + "*" + String(raw.id))} label="Pick set of raws" onChange={handleSelectRaws} />} ) }
AutocompleteForm组件原始代码:
export default function AutocompleteForm(props) { const { label, array, onChange} = props return ( <Autocomplete disablePortal options={array} sx={{ width: 300 }} renderInput={(params) => <TextField {...params} label={label} />} onChange={onChange} /> ) }
解决方案
当然可以直接传递ID,核心是利用Material-UI Autocomplete组件支持对象数组的特性,不用把数据转成带标记的字符串,直接操作原始对象即可,步骤如下:
1. 修改AutocompleteForm组件
让它接收原始对象数组,自定义选项显示内容,并在选中时直接把ID传给父组件:
export default function AutocompleteForm(props) { const { label, options, onChange } = props return ( <Autocomplete disablePortal options={options} sx={{ width: 300 }} // 自定义选项展示内容,只显示name和description renderOption={(props, option) => ( <li {...props}> {option.name}: {option.description} </li> )} renderInput={(params) => <TextField {...params} label={label} />} // 选中时提取ID,传给父组件的回调 onChange={(event, selectedOption) => { if (selectedOption) { onChange(selectedOption.ID) } }} /> ) }
2. 修改父组件代码
直接传入原始对象数组,简化选中逻辑:
import { useEffect, useState } from 'react' const Form = () => { const [allRaws, setAllRaws] = useState([]) const [rawID, setRawID] = useState('') // 用useEffect初始化数据,避免组件无限重渲染 useEffect(() => { setAllRaws([ {"ID" : 1, "name" : "raw1", "description" : "description 1"}, {"ID" : 2, "name" : "raw2", "description" : "description 2"}, {"ID" : 3, "name" : "raw3", "description" : "description 3"}, ]) }, []) // 直接接收选中的ID,更新状态 const handleSelectRaws = (selectedID) => { setRawID(selectedID) } return ( <AutocompleteForm options={allRaws} label="Pick set of raws" onChange={handleSelectRaws} /> ) }
关键修改说明
- 不再把对象转成带
*的字符串,直接传递原始对象数组给Autocomplete,逻辑更清晰 - 通过
renderOption自定义选项的显示内容,完全隐藏ID,提升用户体验 - Autocomplete的onChange直接拿到选中的对象,提取ID后传给父组件,不用再做字符串拆分操作
- 修复了父组件中直接在顶层调用
setAllRaws的问题,改用useEffect初始化数据,避免无限重渲染
内容的提问来源于stack exchange,提问作者Ruo
相关产品推荐
相关产品推荐

