You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MaterialUI Autocomplete问题:重复Key错误与自定义卡片布局实现

解决方案:MaterialUI Autocomplete 两个问题处理

1. 解决重复Key报错问题

  • 不要将options处理为仅含名称的数组,直接传递完整的Items对象数组,避免同名导致的Key冲突
  • 若后端返回数据无itemId,在获取数据时为每个条目生成uuid作为唯一标识
  • 通过getOptionLabel指定输入框显示的文本,用getOptionKey配置使用itemId作为React Key

2. 实现自定义卡片式建议项

  • 使用Autocomplete的renderOption属性自定义每个建议项的布局,无需手动调用.map()
  • 借助MUI的Box、Avatar等组件实现左侧头像、右侧信息的卡片布局

修正后的完整代码

import { Autocomplete, TextField, Typography, Box, Avatar } from "@mui/material";
import { Fragment, useEffect, useState } from "react";
import uuid from "react-uuid";
import agent from "../../../api/agent";
import { Items } from "../../../models/Job";
import { setCloseMenu, setOpenMenu } from "../../menu/menuSlice";
import { useAppDispatch, useAppSelector } from "../../Redux/reduxStore";

interface Props {
    searchTerm?: string;
}

export default function JobSearch(props: Props) {
    const [items, setItems] = useState<Items[]>([]);
    const dispatch = useAppDispatch();
    const { status } = useAppSelector(state => state.menu);

    useEffect(() => {
        agent.Product.getAutoCompleteProducts()
            .then(rawItems => {
                // 为每个商品添加唯一itemId
                const itemsWithId = rawItems.map(item => ({
                    ...item,
                    itemId: uuid()
                }));
                setItems(itemsWithId);
            })
            .catch(error => console.log(error));
    }, []);

    return (
        <Fragment>
            <Autocomplete
                open={status.name === "autoCompleteMenu" && status.open}
                onOpen={() => dispatch(setOpenMenu("autoCompleteMenu"))}
                onClose={() => dispatch(setCloseMenu("autoCompleteMenu"))}
                options={items}
                getOptionLabel={(option) => option.itemName}
                getOptionKey={(option) => option.itemId}
                renderOption={(props, option) => (
                    <Box component="li" {...props} sx={{ 
                        display: 'flex', 
                        alignItems: 'center', 
                        gap: 2, 
                        padding: 2, 
                        cursor: 'pointer',
                        borderBottom: '1px solid #eee'
                    }}>
                        {/* 左侧头像,可替换为实际图片地址 */}
                        <Avatar sx={{ width: 48, height: 48, bgcolor: 'primary.main' }}>
                            {option.itemName.charAt(0)}
                        </Avatar>
                        {/* 右侧商品信息 */}
                        <Box sx={{ flex: 1 }}>
                            <Typography variant="h6" sx={{ fontWeight: 500 }}>{option.itemName}</Typography>
                            <Typography variant="body2" color="text.secondary">${option.itemPrice.toFixed(2)}</Typography>
                            <Typography variant="body2" color="text.secondary" sx={{ marginTop: 0.5 }}>
                                {option.itemDesc}
                            </Typography>
                        </Box>
                    </Box>
                )}
                renderInput={(params) => (
                    <TextField {...params} variant='outlined' placeholder="搜索商品" />
                )}
            />
        </Fragment>
    );
}

关键说明

  • getOptionKey:显式指定用itemId作为每个选项的唯一Key,彻底解决"重复Key"报错
  • renderOption:必须将props解构传入根元素(这里是Box),以保留Autocomplete的选中、高亮等交互逻辑;内部通过弹性布局实现卡片样式
  • 数据处理:在获取后端数据时补充itemId,确保每个条目有唯一标识(若后端已返回itemId可跳过此步骤)

内容的提问来源于stack exchange,提问作者Himanshu Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:35:17