当所有 children 都有钥匙时,反应抱怨 key-less children
React complaining about key-less children when all children have keys
正如标题所说,React 在具有唯一键的列表中抛出关于 children 的错误,我不知道为什么。我正在构建一个 Twitch 聊天克隆,这发生在我的表情选择器上,其中每个可供您使用的表情都列为可点击的图标。我使用的每个地图函数都会吐出带有键的组件。我什至遍历了每个组件并添加了一个唯一的密钥,无论它是否真的需要它,但我仍然收到警告。单击前几个跟踪链接没有任何用处。
我知道我的代码可能不是很清楚,对此我深表歉意,但我们将不胜感激。
这是受影响组件的 return 声明:
return (
<Popover placement="top">
<PopoverTrigger>
<Button disabled={!loggedIn || !connected}>
{
<Box
as="img"
width={[12, 10, 10, 8]}
alt="Emote Picker"
// src="https://static-cdn.jtvnw.net/emoticons/v2/305954156/static/light/3.0" // PogChamp
src="https://static-cdn.jtvnw.net/emoticons/v2/307445021/static/light/3.0" // Orangie
title="Emote Picker"
/>
}
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<Flex height={400} overflow="auto" direction="column">
{showBTTVChannel && (
<>
<PopoverHeader>BTTV Channel Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_channel') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showFFZChannel && (
<>
<PopoverHeader>FFZ Channel Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'ffz_channel') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showBTTVShared && (
<>
<PopoverHeader>BTTV Shared Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_shared') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showEmotes &&
// eslint-disable-next-line array-callback-return
Object.keys(emoteSets.current).map(key => {
if (key !== 'Twitch Global') {
return (
<>
<PopoverHeader>{key}</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(emoteSets.current[key]['emotes']).map(
(key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={
userEmotes[key][
userOptions.emoteQuality + 'x'
]
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
)}
</Flex>
</PopoverBody>
</>
);
}
})}
<PopoverHeader>BTTV Global Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_global') {
return (
<ChatEmote
key={index}
name={key}
src={bttvEmotes[key][userOptions.emoteQuality + 'x']}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
{showEmotes && (
<>
<PopoverHeader>Twitch Global</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(
emoteSets.current['Twitch Global']['emotes']
).map((key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={userEmotes[key][userOptions.emoteQuality + 'x']}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
})}
</Flex>
</PopoverBody>
</>
)}
</Flex>
</PopoverContent>
</Popover>
);
密钥必须添加到您要返回的父包装器组件
密钥丢失 -->
{showEmotes &&
// eslint-disable-next-line array-callback-return
//map second argument return the index of current element
Object.keys(emoteSets.current).map((key,i) => {
if (key !== 'Twitch Global') {
return (
//missing key
<div key={i}>
<PopoverHeader>{key}</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(emoteSets.current[key]['emotes']).map(
(key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={
userEmotes[key][
userOptions.emoteQuality + 'x'
]
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
)}
</Flex>
</PopoverBody>
</>
这能解决问题吗?
正如标题所说,React 在具有唯一键的列表中抛出关于 children 的错误,我不知道为什么。我正在构建一个 Twitch 聊天克隆,这发生在我的表情选择器上,其中每个可供您使用的表情都列为可点击的图标。我使用的每个地图函数都会吐出带有键的组件。我什至遍历了每个组件并添加了一个唯一的密钥,无论它是否真的需要它,但我仍然收到警告。单击前几个跟踪链接没有任何用处。
我知道我的代码可能不是很清楚,对此我深表歉意,但我们将不胜感激。
这是受影响组件的 return 声明:
return (
<Popover placement="top">
<PopoverTrigger>
<Button disabled={!loggedIn || !connected}>
{
<Box
as="img"
width={[12, 10, 10, 8]}
alt="Emote Picker"
// src="https://static-cdn.jtvnw.net/emoticons/v2/305954156/static/light/3.0" // PogChamp
src="https://static-cdn.jtvnw.net/emoticons/v2/307445021/static/light/3.0" // Orangie
title="Emote Picker"
/>
}
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<Flex height={400} overflow="auto" direction="column">
{showBTTVChannel && (
<>
<PopoverHeader>BTTV Channel Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_channel') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showFFZChannel && (
<>
<PopoverHeader>FFZ Channel Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'ffz_channel') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showBTTVShared && (
<>
<PopoverHeader>BTTV Shared Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_shared') {
return (
<ChatEmote
key={index}
name={key}
src={
bttvEmotes[key][userOptions.emoteQuality + 'x']
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
</>
)}
{showEmotes &&
// eslint-disable-next-line array-callback-return
Object.keys(emoteSets.current).map(key => {
if (key !== 'Twitch Global') {
return (
<>
<PopoverHeader>{key}</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(emoteSets.current[key]['emotes']).map(
(key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={
userEmotes[key][
userOptions.emoteQuality + 'x'
]
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
)}
</Flex>
</PopoverBody>
</>
);
}
})}
<PopoverHeader>BTTV Global Emotes</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{bttvEmotes !== null &&
// eslint-disable-next-line array-callback-return
Object.keys(bttvEmotes).map((key, index) => {
if (bttvEmotes[key]['category'] === 'bttv_global') {
return (
<ChatEmote
key={index}
name={key}
src={bttvEmotes[key][userOptions.emoteQuality + 'x']}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
})}
</Flex>
</PopoverBody>
{showEmotes && (
<>
<PopoverHeader>Twitch Global</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(
emoteSets.current['Twitch Global']['emotes']
).map((key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={userEmotes[key][userOptions.emoteQuality + 'x']}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
})}
</Flex>
</PopoverBody>
</>
)}
</Flex>
</PopoverContent>
</Popover>
);
密钥必须添加到您要返回的父包装器组件 密钥丢失 -->
{showEmotes &&
// eslint-disable-next-line array-callback-return
//map second argument return the index of current element
Object.keys(emoteSets.current).map((key,i) => {
if (key !== 'Twitch Global') {
return (
//missing key
<div key={i}>
<PopoverHeader>{key}</PopoverHeader>
<PopoverBody>
<Flex flexWrap="wrap">
{emoteSets.current !== null &&
Object.keys(emoteSets.current[key]['emotes']).map(
(key, index) => {
return (
<ChatEmote
key={index}
name={key}
src={
userEmotes[key][
userOptions.emoteQuality + 'x'
]
}
height={8}
margin={1.5}
onClick={() => onClickHandler(key)}
/>
);
}
)}
</Flex>
</PopoverBody>
</>
这能解决问题吗?