react-native-elements
react-native-elements copied to clipboard
React Native 0.78 ListItem.Accordion Each child in a list should have a unique "key" prop.
Is there an existing issue for this?
- [x] I have searched the existing issues
Explain what you did
I directly copied the following code in React Native 0.78 version
Expected behavior
“Each child in a list should have a unique "key" prop. Check the render method of View. It was passed a child from PadView.”
Describe the bug
I have already set the key, but this error still occurred
“Each child in a list should have a unique "key" prop. Check the render method of View. It was passed a child from PadView.”
Steps To Reproduce


“Each child in a list should have a unique "key" prop. Check the render method of `View`. It was passed a child from PadView.”
Screenshots
No response
Your Environment
Global Dependencies:
No related dependency found
Local Dependencies:
- @rneui/base : ^4.0.0-rc.8
- @rneui/themed : ^4.0.0-rc.8
- react : 18.3.1
- react-native : 0.78.0
- @types/react : ^19
@rneui/base : ^4.0.0-rc.8 @rneui/themed : ^4.0.0-rc.8 react : 19 react-native : 0.78.0 @types/react : ^19
I upgraded my project from rn0.68 to rn0.78 along with rneui upgrade and have same issue.
It seems if multiple items are under <ListItem>, the warning is displayed. Here are simplified demonstrations of the issue. To demonstrate the problem, I added keys at all levels.
Example 1:
<FlatList
keyExtractor={(item) => item.itemID}
data={[{itemID: "aaaa"}]}
renderItem={({ item }) => {
return (
<ListItem key={"item" + item.itemID} >
<ListItem.Title key={"title" + item.itemID} >{"bcd"}</ListItem.Title>
<ListItem.Subtitle key={"Subtitle" + item.itemID}>{"bcd"}</ListItem.Subtitle>
</ListItem>);
}}
/>
Example 2:
<FlatList
keyExtractor={(item) => item.itemID}
data={[{itemID: "aaaa"}]}
renderItem={({ item }) => {
return (
<ListItem key={"item" + item.itemID}>
<Avatar key={"avatar" + item.itemID} title="abc" />
<ListItem.Content key={"content" + item.itemID}></ListItem.Content>
</ListItem>);
}}
/>
Quick fix with patch-package https://github.com/ds300/patch-package#readme
diff --git a/node_modules/@rneui/base/dist/ListItem/components/PadView.js b/node_modules/@rneui/base/dist/ListItem/components/PadView.js
index 0e90243..d352736 100644
--- a/node_modules/@rneui/base/dist/ListItem/components/PadView.js
+++ b/node_modules/@rneui/base/dist/ListItem/components/PadView.js
@@ -11,13 +11,30 @@ var __rest = (this && this.__rest) || function (s, e) {
};
import React, { useRef } from 'react';
import { View } from 'react-native';
+
export const PadView = (_a) => {
var { children, pad, Component } = _a, props = __rest(_a, ["children", "pad", "Component"]);
const _root = useRef(null);
const length = React.Children.count(children);
const Container = Component || View;
- return (React.createElement(Container, Object.assign({}, props, { ref: _root, testID: "RNE__LISTITEM__padView" }), React.Children.map(children, (child, index) => child && [
- child,
- index !== length - 1 && React.createElement(View, { style: { paddingLeft: pad } }),
- ])));
+
+ return (
+ React.createElement(
+ Container,
+ Object.assign({}, props, { ref: _root, testID: "RNE__LISTITEM__padView" }),
+ React.Children.map(children, (child, index) =>
+ child && [
+ React.cloneElement(child, { key: `child-${index}` }),
+ index !== length - 1 &&
+ React.createElement(
+ View,
+ {
+ style: { paddingLeft: pad },
+ key: `separator-${index}`
+ }
+ ),
+ ]
+ )
+ )
+ );
};
\ No newline at end of file
@FTW-001 This library is no longer maintained and if you wish you can use fork of this library where this issues is fixed and also some other issues are also fixed there.
Fork Repo React Native Vikalp Elements
@FTW-001 This library is no longer maintained and if you wish you can use fork of this library where this issues is fixed and also some other issues are also fixed there.
Fork Repo React Native Vikalp Elements
There was a post from one of the mods in this thread (https://github.com/react-native-elements/react-native-elements/discussions/3925) that says that they intend to revive it.
I replaced ListItem.Accordion with your a custom Accordion component using Expo-compatible components like Pressable, Animated, and View.
// components/AccordionItem.tsx
import React, { useEffect, useRef } from 'react'
import {
View,
Text,
Pressable,
LayoutAnimation,
Platform,
UIManager,
Animated,
} from 'react-native'
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental?.(true)
}
interface AccordionItemProps {
title: string
description: string
isExpanded: boolean
onPress: () => void
}
const AccordionItem: React.FC<AccordionItemProps> = ({
title,
description,
isExpanded,
onPress,
}) => {
const rotateAnim = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing(rotateAnim, {
toValue: isExpanded ? 1 : 0,
duration: 200,
useNativeDriver: true,
}).start()
}, [isExpanded, rotateAnim])
const rotation = rotateAnim.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '180deg'],
})
const handlePress = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
onPress()
}
return (
<View className="bg-white border-b border-gray-200">
<Pressable
onPress={handlePress}
className="flex-row items-center justify-between px-4 py-3"
accessibilityRole="button"
accessibilityState={{ expanded: isExpanded }}
>
<Text className="flex-1 text-base font-semibold text-black">
{title}
</Text>
<Animated.View style={{ transform: [{ rotate: rotation }] }}>
<Ionicons name="chevron-down" size={20} color="black" />
</Animated.View>
</Pressable>
{isExpanded && (
<View className="px-4 py-3 bg-gray-100">
<Text className="leading-6 text-black">{description}</Text>
</View>
)}
</View>
)
}
export default AccordionItem```
// in the component
``` const handleAccordionPress = (index: number) => {
const newLoadingStates = loadingStates.map((_, i) => i === index)
setLoadingStates(newLoadingStates)
setExpandedIndex((prevIndex) => (prevIndex === index ? null : index))
setTimeout(() => {
setLoadingStates(loadingStates.map(() => false))
// Check if the last accordion is expanded
if (index === steps.length - 1 && scrollViewRef.current) {
// Scroll to the end of the ScrollView
scrollViewRef.current.scrollToEnd({ animated: true })
}
}, 100)
}
<View className="bg-white shadow-sm pb-[80px]">
{steps.map((item, index) => (
<AccordionItem
key={item.id}
title={item.title}
description={item.description}
isExpanded={expandedIndex === index}
onPress={() => handleAccordionPress(index)}
/>
))}
</View>```
Seems like there was some additional formatting to the patch file in claudiozam's comment above.
Here is a super minimal diff generated by patch-package - all it adds is the ", key: PadView-${index}" to the View component.
This solved the issue for me on Accordion and also the @rneui/themed ListItem I was using elsewhere. Not 100% sure why this wasn't a problem with react 18 though.
diff --git a/node_modules/@rneui/base/dist/ListItem/components/PadView.js b/node_modules/@rneui/base/dist/ListItem/components/PadView.js
index 0e90243..3f743bd 100644
--- a/node_modules/@rneui/base/dist/ListItem/components/PadView.js
+++ b/node_modules/@rneui/base/dist/ListItem/components/PadView.js
@@ -18,6 +18,6 @@ export const PadView = (_a) => {
const Container = Component || View;
return (React.createElement(Container, Object.assign({}, props, { ref: _root, testID: "RNE__LISTITEM__padView" }), React.Children.map(children, (child, index) => child && [
child,
- index !== length - 1 && React.createElement(View, { style: { paddingLeft: pad } }),
+ index !== length - 1 && React.createElement(View, { style: { paddingLeft: pad }, key: `PadView-${index}` }),
])));
};