版本與環境
@mui/material: 5.15.15使用方式
重點:過去當作 props 傳給 Autocomplete 元件的內容,改為 args 傳給 useAutocomplete()。以前的寫法是:
const [value, setValue] = useState<string | null>(options[0]);
<Autocomplete value={value} onChange={(_, newValue: string | null) => { setValue(newValue); }} options={options}/>;改為:
const [input, setInput] = useState(types[0]);
const { getRootProps, getInputLabelProps, getInputProps, getListboxProps, getOptionProps, groupedOptions,} = useAutocomplete({ getOptionLabel: (option) => option, onChange: (_: React.SyntheticEvent, value) => { if (value) setInput(value); }, id, value: input, options: types,});
const rootProps = getRootProps();const inputLabelProps = getInputLabelProps();const inputProps = getInputProps();const listBoxProps = getListboxProps();
<section> <div {...rootProps}> <label {...inputLabelProps} className="label"> UseAutocomplete </label> <input {...inputProps} className="input" /> </div> {groupedOptions.length > 0 ? ( <ul {...listBoxProps} className="listBox"> {(groupedOptions as typeof types).map((option, index) => ( <li {...getOptionProps({ option, index })} className="list"> {option} </li> ))} </ul> ) : null}</section>;完整的程式碼放這裡。
useAutocomplete 的優點:
- 完全控制
Autocomplete的 HTML 元素與結構 - 最大的樣式自由度,不用擔心 MUI 先貼了什麼樣式到元件上
缺點是要從 useAutocomplete 回傳的 cbs 產生各層級(root / inputLabel / input / listBox / option)的 props 並依序傳入。程式碼讀起來確實很冗長,但個人認為瑕不掩瑜。
那麼 props.renderInput 呢?
心得:雞肋(使用方式可參考官方文件)。
雖然可以靠 props.renderInput 自定義輸入框的元素與樣式,但需要回頭靠 props.classes 慢慢覆蓋掉 MUI 預設的 paper listbox 與 option 樣式(參考官方複雜樣式範例)。
在需要大量樣式客製化的前提下,處理起來沒有比用 useAutocomplete 輕鬆。