如何向 React/Material UI 自动完成组件添加唯一键?

kou*_*ami 61 javascript jsx reactjs material-ui

我正在尝试创建一个Autocomplete实质上仅向用户显示搜索结果的 Material UI 组件。某些选项的名称可能会重复,但它们都有唯一的 ID。我收到以下警告:

\n
\n

index.js:1 警告:遇到两个具有相同键的子项,Name B。密钥应该是唯一的,以便组件在更新时保持其身份。非唯一的键可能会导致子项重复和/或省略 \xe2\x80\x94 该行为不受支持,并且可能在未来版本中更改。

\n
\n
const SearchField = () => {\n    const [open, setOpen] = React.useState(false)\n    const [searchQuery, setSearchQuery] = React.useState('')\n    const [searchResults, setSearchResults] = React.useState([])\n    const loading = true //later\n\n    const debounced = useDebouncedCallback(\n        async searchQuery => {\n            if (searchQuery) {\n                let result = await doSearch(searchQuery)\n                if (result.status === 200) {\n                    setSearchResults(result.data)\n                } else {\n                    console.error(result)\n                }\n            }\n        },\n        1000\n    )\n\n    const handleInputChange = e => {\n        if (e.target.value && e.target.value !== searchQuery) {\n            debounced(e.target.value)\n            setSearchQuery(e.target.value)\n        }\n    }\n\n    const options = [{\n        name: 'Name A',\n        id: 'entry_0597856'\n    },{\n        name: 'Name B',\n        id: 'entry_3049854'\n    },{\n        name: 'Name B',\n        id: 'entry_3794654'\n    },{\n        name: 'Name C',\n        id: 'entry_9087345'\n    }]\n\n\n    return (\n        <Autocomplete\n            id='search_freesolo'\n            freeSolo\n            selectOnFocus\n            clearOnBlur\n            handleHomeEndKeys\n            autoHighlight\n            onInputChange={handleInputChange}\n            open={true}\n            onOpen={() => setOpen(true)}\n            onClose={() => setOpen(false)}\n            loading={loading}\n            key={option => option.id}\n\n            options={options}\n            getOptionLabel={option => option.name}\n\n            renderOption={(props, option) => (\n                <Box\n                    component='li'\n                    {...props}\n                >\n                    {option.name}\n                </Box>\n            )}\n\n            renderInput={params => {\n                return (\n                    <TextField\n                        {...params}\n                        required\n                        id="search_bar"\n                        label="Search"\n                        InputProps={{\n                            ...params.InputProps,\n                            endAdornment: (\n                                <React.Fragment>\n                                    {loading ? <CircularProgress size={18} /> : null}\n                                    {params.InputProps.endAdornment}\n                                </React.Fragment>\n                            )\n                        }}\n                    />\n                )}\n            }\n            \n        />\n    )\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Nea*_*arl 129

您可以定义自己的renderOption,可以返回具有正确键值的列表项。您的代码抱怨重复的密钥,因为默认情况下,Autocomplete 使用 getOptionLabel(option)来检索密钥:

<Autocomplete
  renderOption={(props, option) => {
    return (
      <li {...props} key={option.id}>
        {option.name}
      </li>
    );
  }}
  renderInput={(params) => <TextField {...params} label="Movie" />}
/>
Run Code Online (Sandbox Code Playgroud)

如果仍然不起作用,请检查您的 props 顺序,如果您将 key props 放在回调提供的 props 之前,则需要最后声明 key props:

<Box component='li' key={key} {...props}
Run Code Online (Sandbox Code Playgroud)

然后它将被props.keyMUI 覆盖。应该是这样的:

<Box component='li' {...props} key={key}
Run Code Online (Sandbox Code Playgroud)

现场演示

Codesandbox 演示

  • @kougami你需要最后声明`key`属性,如果你把它放在回调提供的`props`之前,比如`&lt;Box component='li' key={} {...props}`那么它将是被 MUI 中的“props.key”覆盖。 (5认同)
  • 恐怕它对我来说不是那样工作 - 当我使用 &lt;Box component='li' key={option.id}&gt; 时, option.name 似乎被用作密钥。我可以看到它的工作方式与演示中的一样,但是演示中的代码只是来自 MUI 文档,而不是我自己的代码,如果我没有记错的话? (3认同)
  • 太疯狂了,事情是如此简单。但现在我已经学到了一些东西,以后我会把 {...props} 放在第一位!非常感谢您的帮助并帮助我理解。 (3认同)