网站搜索

javascript - 如何将唯一分组用于 MUI 的自动完成组件?


我正在使用 MUI 的自动完成(Autocomplete)在搜索栏中对我的建议进行分组。我认为这看起来很简单,但其实不是。首先,请看看我的数据结构。

[{ 
"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"
}, ... ]

现在你可以看到,有 3 本由 'Colin Hoover' 撰写的书,放置在不同的 ID 上。我想要实现的是,我的 MUI 自动完成组件应该渲染

 Colin Hoover //author name as heading and books underneath it
     Remainders of Him 
     It Ends with us
     It starts with us 
     ... other books from this specific author

到我的 MUI 的 Autocomplete 中的 groupBy 属性。

我现在遇到的问题 - 当我将某位作者的书籍按连续的 ID 排列(比如 id: 1, 2, 3, 4 ..)时,自动完成的分组功能工作正常(即,如果某位作者的书籍出现在连续的 ID 中,它会将这些不同的书籍分组到同一作者下)。但是,当我以随机顺序排列它们时(即 id 1, 3, 5, 8, 9 ..包含同名 "Colin Hoover" 的书籍),它就不会进行任何分组,而是会在自动建议列表中创建重复的标题 "Colin Hoover",这是我不希望发生的。

我只想在 MUI 的自动完成中显示相同的标题以及他/她以自己名义写的所有书籍。

这是我的代码

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}`
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>
    )
}

我知道我必须在 groupBy 中实现 'sort',但如何做到同样的事情,以便根据作者姓名对所有书籍进行排序并将其作为 groupBy 属性的参数传递。

所有建议都欢迎并高度赞赏。