so i try to render an array of object into react js component like below:
import React, { useState } from "react";
import { Route, Link } from "react-router-dom";
import {
MdOutlineSpaceDashboard,
MdOutlineStorage,
MdOutlineFactCheck,
MdOutlineCalculate,
MdStickyNote2,
MdAssignmentTurnedIn,
MdOutlineDynamicForm,
MdOutlineArrowDropDown,
} from "react-icons/md";
import { BsChevronDown, BsArrowLeftShort } from "react-icons/bs";
import Logo_Nabati from "../assets/logo-nabati.svg";
const menuItems = [
{ id: 1, label: "Dashboard", icon: MdOutlineSpaceDashboard, link: "/" },
{
id: 2,
label: "Master Data",
icon: MdOutlineStorage,
iconArrow: MdOutlineArrowDropDown,
link: "",
subMenu: true,
subMenuItems: [
{ id: 1, label: "KSBT", link: "/MasterData/list/KSBT" },
{ id: 2, label: "SQ01_RM", link: "/MasterData" },
{ id: 3, label: "SQ01_PM", link: "/MasterData" },
{ id: 4, label: "Depre", link: "/MasterData" },
{ id: 5, label: "OMC", link: "/MasterData" },
{ id: 6, label: "Premix", link: "/MasterData" },
{ id: 7, label: "Routing", link: "/MasterData" },
{ id: 8, label: "MP", link: "/MasterData" },
],
},
{ id: 3, label: "Check COGM", icon: MdOutlineFactCheck, link: "/checkcogm" },
{
id: 4,
label: "Calculation",
icon: MdOutlineCalculate,
link: "/calculation",
},
{
id: 5,
label: "Draft Calculation",
icon: MdStickyNote2,
link: "/draft",
},
{ id: 6, label: "Approved", icon: MdAssignmentTurnedIn, link: "/approval" },
{ id: 7, label: "Task Activity", icon: MdOutlineDynamicForm, link: "/task" },
];
const Sidebar = () => {
const [open, setOpen] = useState(false);
const [submenuOpen, setSubmenuOpen] = useState(false);
return (
<div className="flex">
<div
className={` bg-yellow-400 h-screen p-5 pt-8 ${
open
? "w-50 ease-out delay-150 peer-focus:left-0 duration-200"
: "w-20 ease-out delay-150 peer-focus:left-0 duration-200"
} duration-300 relative`}
>
<BsArrowLeftShort
className={` bg-white text-yellow-300 text-3xl rounded-full absolute -right-3 top-9 border border-yellow-300 cursor-pointer delay-150 duration-200 ${
!open && "rotate-180"
}`}
onClick={() => setOpen(!open)}
/>
<div className={`inline-flex`}>
<img src={Logo_Nabati} width={123} height={75} alt="logo Nabati" />
</div>
<ul className="pt-8">
{menuItems.map(
({ icon: Icon, iconArrow: IconArrow, ...menu }, index) => (
<>
<Link to={menu.link}>
<li
key={index}
className="text-white text-sm text-justify flex items-center gap-x-4 cursor-pointer p-2 hover:bg-red-600 rounded-md mt-2"
>
<Icon className="text-2xl text-white group-hover:text-red-600" />
<span
className={`text-base font-mendium flex-1 duration-200 ${
!open && "hidden"
} `}
>
{menu.label}
</span>
{menu.subMenu && (
<BsChevronDown
className={`text-base font-mendium duration-200 ${
!open && "hidden"
} ${submenuOpen && "rotate-180"}`}
onClick={() => {
setSubmenuOpen(!submenuOpen);
}}
/>
)}
</li>{" "}
</Link>
{menu.subMenu && submenuOpen && open && (
<ul>
{menu.subMenuItems.map((subMenuItem, index) => (
<Link to={subMenuItem.link}>
<li
key={index}
className="text-white text-sm flex items-center gap-x-4 cursor-pointer p-1 px-12 hover:bg-red-500 rounded-md"
>
{subMenuItem.label}
</li>{" "}
</Link>
))}
</ul>
)}
</>
)
)}
</ul>
</div>
</div>
);
};
export default Sidebar;
even after i put the key={index} on the
react-jsx-dev-runtime.development.js:119 Warning: Each child in a list should have a unique "key" prop.
can someone tell me where di i do wrong here, it supposed to be no problem after i put the key={item} but why i still gettingn error on the console?
CodePudding user response:
do the following
import React, { useState } from "react";
import { Route, Link } from "react-router-dom";
import {
MdOutlineSpaceDashboard,
MdOutlineStorage,
MdOutlineFactCheck,
MdOutlineCalculate,
MdStickyNote2,
MdAssignmentTurnedIn,
MdOutlineDynamicForm,
MdOutlineArrowDropDown,
} from "react-icons/md";
import { BsChevronDown, BsArrowLeftShort } from "react-icons/bs";
import Logo_Nabati from "../assets/logo-nabati.svg";
const menuItems = [
{ id: 1, label: "Dashboard", icon: MdOutlineSpaceDashboard, link: "/" },
{
id: 2,
label: "Master Data",
icon: MdOutlineStorage,
iconArrow: MdOutlineArrowDropDown,
link: "",
subMenu: true,
subMenuItems: [
{ id: 1, label: "KSBT", link: "/MasterData/list/KSBT" },
{ id: 2, label: "SQ01_RM", link: "/MasterData" },
{ id: 3, label: "SQ01_PM", link: "/MasterData" },
{ id: 4, label: "Depre", link: "/MasterData" },
{ id: 5, label: "OMC", link: "/MasterData" },
{ id: 6, label: "Premix", link: "/MasterData" },
{ id: 7, label: "Routing", link: "/MasterData" },
{ id: 8, label: "MP", link: "/MasterData" },
],
},
{ id: 3, label: "Check COGM", icon: MdOutlineFactCheck, link: "/checkcogm" },
{
id: 4,
label: "Calculation",
icon: MdOutlineCalculate,
link: "/calculation",
},
{
id: 5,
label: "Draft Calculation",
icon: MdStickyNote2,
link: "/draft",
},
{ id: 6, label: "Approved", icon: MdAssignmentTurnedIn, link: "/approval" },
{ id: 7, label: "Task Activity", icon: MdOutlineDynamicForm, link: "/task" },
];
const Sidebar = () => {
const [open, setOpen] = useState(false);
const [submenuOpen, setSubmenuOpen] = useState(false);
return (
<div className="flex">
<div
className={` bg-yellow-400 h-screen p-5 pt-8 ${
open
? "w-50 ease-out delay-150 peer-focus:left-0 duration-200"
: "w-20 ease-out delay-150 peer-focus:left-0 duration-200"
} duration-300 relative`}
>
<BsArrowLeftShort
className={` bg-white text-yellow-300 text-3xl rounded-full absolute -right-3 top-9 border border-yellow-300 cursor-pointer delay-150 duration-200 ${
!open && "rotate-180"
}`}
onClick={() => setOpen(!open)}
/>
<div className={`inline-flex`}>
<img src={Logo_Nabati} width={123} height={75} alt="logo Nabati" />
</div>
<ul className="pt-8">
{menuItems.map(
({ icon: Icon, iconArrow: IconArrow, ...menu }, index) => (
<div key={menu.id}>
<Link to={menu.link}>
<li
className="text-white text-sm text-justify flex items-center gap-x-4 cursor-pointer p-2 hover:bg-red-600 rounded-md mt-2"
>
<Icon className="text-2xl text-white group-hover:text-red-600" />
<span
className={`text-base font-mendium flex-1 duration-200 ${
!open && "hidden"
} `}
>
{menu.label}
</span>
{menu.subMenu && (
<BsChevronDown
className={`text-base font-mendium duration-200 ${
!open && "hidden"
} ${submenuOpen && "rotate-180"}`}
onClick={() => {
setSubmenuOpen(!submenuOpen);
}}
/>
)}
</li>{" "}
</Link>
{menu.subMenu && submenuOpen && open && (
<ul>
{menu.subMenuItems.map((subMenuItem, index) => (
<Link to={subMenuItem.link} key={`${menu.id}-${subMenuItem.id}`}>
<li
key={index}
className="text-white text-sm flex items-center gap-x-4 cursor-pointer p-1 px-12 hover:bg-red-500 rounded-md"
>
{subMenuItem.label}
</li>{" "}
</Link>
))}
</ul>
)}
</div>
)
)}
</ul>
</div>
</div>
);
};
export default Sidebar;
you need to add the key to the first element inside the map in your code the first element is a fragment
<></>
that way is not working when you do it on the
<li key={index}
also avoid to use index it will trigger a warning and is better practice use a unique identifier