如何在MUI Autocomplete中实现按作者的唯一分组
问题:MUI Autocomplete分组重复,同一作者书籍分散
问题说明
使用MUI的Autocomplete组件实现搜索栏建议项分组时,同一作者的书籍ID不连续会生成重复的作者分组头,仅当ID连续时分组正常。需要将同一作者的所有书籍归到同一个分组下。
数据结构
[ { "id" : 1, "bookName" : "it starts with us", "author" : "Colin Hoover" }, { "id" : 2, "bookName" : "it ends with us", "author" : "Colin Hoover" }, { "id" : 3, "bookName" : "The great Gatsby", "author" : "Scott Fitzgerald" }, { "id" : 4, "bookName" : "To Kill a mocking bird", "author" : "Harper Lee" }, { "id" : 5, "bookName" : "Remainders of Him", "author" : "Colin Hoover" } ]
期望渲染效果
Colin Hoover // 作者名作为分组标题,下方列出其书籍 Remainders of Him It Ends with us It starts with us ... 该作者的其他书籍 Scott Fitzgerald The great Gatsby Harper Lee To Kill a mocking bird
当前代码
imports ... export default function JobSearch () { const [ books, setBooks ] = useState<Book[]>([]); const [ searchTerm, setSearchTerm ] = useState<string>(''); // using redux const dispatch = useAppDispatch(); const { status } = useAppSelector ( state => state.menu ); useEffect(() => { agent.Books.getBooks() // my endpoint for getting the books .then((books) => { setBooks(books); console.log(books)}) .catch((error) => console.log(error)) }, []); const suggestions = books.map((book) => { const bookDetail = `${book.name} by ${book.author}` // 注意:这里book.name应该是book.bookName,数据结构中字段是bookName return { bookDetail, ...book }}); const handleChangeInput = ( event : any ) => { setSearchTerm( event.target.value); console.log(event.target.value); } return ( <Fragment> <Autocomplete open = { status.name === "autoCompleteMenu" && status.open } autoHighlight = {true} autoComplete = {true} noOptionsText = {`Search for ${searchTerm}`} onOpen = { () => { dispatch(setOpenMenu("autoCompleteMenu")); }} onClose = { () => dispatch(setCloseMenu("autoCompleteMenu"))} options = {suggestions.sort((a, b) => -b.bookDetail.localeCompare(a.bookDetail))} isOptionEqualToValue = {(option, value) => option.bookDetail === value.bookDetail} groupBy = {(option) => option.author} // I want all books sorted under same author getOptionLabel={(option) => option.bookDetail} renderInput = {(params) => ( <TextField { ...params} label = {'search ...'} onChange = {handleChangeInput} variant = {'outlined'} /> )} /> </Fragment> ) }
解决方案
问题根源在于当前排序逻辑仅按bookDetail倒序,没有先按作者分组排序,导致同一作者的书籍分散在数组中。MUI Autocomplete的groupBy是遍历数组时,遇到新的分组值就创建新分组头,因此必须让同一作者的所有项连续排列。
修改步骤:
- 修正字段错误:
book.name改为book.bookName,匹配数据结构中的字段名。 - 调整排序逻辑:先按作者名排序,确保同一作者的项连续,再按书名排序。
修改后的关键代码:
// 修正suggestions中的字段错误 const suggestions = books.map((book) => { const bookDetail = `${book.bookName} by ${book.author}` return { bookDetail, ...book }}); // 修改Autocomplete的options排序逻辑 options={suggestions.sort((a, b) => { // 先按作者名升序排列,确保同一作者的项连续 const authorCompare = a.author.localeCompare(b.author); if (authorCompare !== 0) { return authorCompare; } // 作者相同时,按书名升序排列(如需倒序可改为 -a.bookName.localeCompare(b.bookName)) return a.bookName.localeCompare(b.bookName); })}
说明:
- 先按
author排序,保证同一作者的所有书籍在数组中连续排列,Autocomplete遍历到这些项时只会生成一个分组头。 - 作者相同的情况下,可根据需求按书名升序/倒序排列,优化展示顺序。
内容的提问来源于stack exchange,提问作者Himanshu Sharma
相关产品推荐
相关产品推荐

