I recently crafted a Dropdown component in React Native. However, I faced a challenge where the Flatlist content ended up positioned beneath the subsequent Dropdown component. This positioning issue prompted me to review my code. Here's the code snippet for reference:
Dropdown Component:
export const DropDown = ({
className,
setSelectedValue,
label,
defaultValue,
padding,
options,
}) => {
const [value, setValue] = useState({});
const [show, setShow] = useState(false);
const labelTranslateY = new Animated.Value(
value?.label || defaultValue ? -7 : 11
);
const handleToggle = () => {
setShow((prev) => !prev);
};
const handlePress = (item) => {
setValue(item);
setSelectedValue(item);
setShow((prev) => !prev);
};
const renderItem = ({ item }) => (
<TouchableOpacity onPress={() => handlePress(item)}>
<View
style={{}}
className=" hover:bg-black cursor-pointer border-b border-gray-600/25 w-full flex flex-wrap flex-row "
>
<Text className="flex-1 py-1 px-2 text-left text-base ">
{item?.label || ""}
</Text>
</View>
</TouchableOpacity>
);
return (
<View
className={`w-full h-full z-10 border-2 border-[#A7A7A7] ${
value?.label || defaultValue ? `bg-white` : `bg-[#E8E8E8]`
} rounded-md flex flex-row justify-between items-center p y-1 px-2 ${className}`}
>
<TouchableOpacity className="w-full z-10" onPress={handleToggle}>
<View className="w-full flex z-10 flex-row justify-between items-center">
<Text className="text-xs z-10">{value?.label || defaultValue}</Text>
<FontAwesomeIcon
icon={show ? faCaretUp : faCaretDown}
style={{ width: "1.5rem", height: "1.5rem", color: "#A7A7A7" }}
/>
</View>
</TouchableOpacity>
<Animated.Text
style={[
styles.label,
{
transform: [{ translateY: labelTranslateY }],
backgroundColor:
value?.label || defaultValue ? "white" : "transparent",
},
]}
>
{label}
</Animated.Text>
{show ? (
<View
className={
`${Platform.OS ==="web" ? "w-full" : "w-[106%]"} z-10 rounded-md overflow-hidden absolute right-0 top-[100%]`
}
>
<FlatList
data={options}
className=" w-full border z-10 border-gray-300 rounded-sm bg-gray-100 shadow-2xl "
renderItem={renderItem}
keyExtractor={(item, index) => item.value}
/>
</View>
) : (
<View></View>
)}
</View>
);
};
index.js
const OverlapExample = () => {
const [filters, setFilters] = useState({});
const options = [
{ label: "jjjjj", value: "1" },
{ label: "kkkkk", value: "2" },
{ label: "lllll", value: "3" },
];
const structData = [
{
options: options,
value: 55,
class: "h-12 p-1 w-1/4",
name: "counter",
label: "Counter",
},
{
options: options,
value: 55,
class: "h-12 p-1 w-1/4",
name: "category",
label: "Category",
},
{
options: options,
value: 55,
class: "h-12 p-1 w-1/4",
name: "collection",
label: "Collection",
},
];
const handleChange = (e, name) => {
setFilters((prev) => {
const newObject = { ...prev };
newObject[`${name}`] = e;
return newObject;
});
};
return (
<View className="w-full">
{structData?.map((item, index) => {
return (
<View key={index} className={`${item.class}`}>
<DropDown
setSelectedValue={(e) => handleChange(e, item.name)}
options={item.options}
label={item.label}
className={`border-2 border-[#A7A7A7] rounded-md py-1 px-2`}
defaultValue={item.label || ""}
/>
</View>
);
})}
</View>
);
};
Result:
I'm currently exploring ways to address this problem and ensure that the Flatlist content properly aligns with the Dropdown component as intended in the layout.
Just add greater zIndex
property to top level dropdown
and decrease it to lower level dropdown.
Example
counter dropdown have : zIndex: 10000
category dropdown have : zIndex: 1000
collection dropdown have : zIndex: 100
hope it will help.