使用 React 和 map 时如何只折叠一个 div [英] How to Collapse only one div when using React and map
问题描述
我正在尝试使用 React 创建一个动态菜单,但我正在努力实现折叠功能.我首先使用一个工作正常的 Json 对象映射每个 MenuItem.之后,当我尝试在单击时实现折叠功能时,所有菜单项都会折叠,而不仅仅是被单击的菜单项.我尝试实现一个在真/假之间切换的数组,但在单击时无法访问该值.代码如下:
import React, { Component } from "react";从样式组件"导入样式;导入./sidebar.css";从反应引导/折叠"导入折叠const 仪表板项目 = [{编号:1,title: "仪表盘",字幕:[分析"、监控"、工作场所"]、文字:Anim pariatur cliche reprehenderit,enim eiusmod high life accusamus terry richardson ad squid.Nihil anim keffiyeh helvetica,精酿啤酒labore wes anderson cred nesciunt sapiente ea proident."},{编号:2,title: "表格",字幕:[基本形式"、步骤形式"、高级形式"]、文字:enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica,craft beerlabore wes anderson cred nesciunt sapiente ea proident."},{编号:3,title: "列表",字幕:[搜索表"、基本列表"、卡片列表"]、文字:理查森广告鱿鱼.Nihil anim keffiyeh helvetica,精酿啤酒labore wes anderson cred nesciunt sapiente ea proident."},{编号:4,title: "个人资料",字幕:[基本资料"、高级资料"]、文字:Nihil anim keffiyeh helvetica,精酿啤酒,wes anderson cred nesciunt sapiente ea proident."},{编号:5,title: "结果",字幕:[成功",失败"],文字:精酿啤酒,韦斯·安德森 (wes anderson) 信用 nesciunt sapiente ea proident."},{编号:6,title: "账户",字幕:[账户中心"、账户设置"]、文字:wes anderson cred nesciunt sapiente ea proident."}];功能侧边栏(){const [open, setOpen] = React.useState(false);const [clickedItems, setClickedItems] = React.useState( [false, false, false, false, false, false] );函数 handleClick(id) {console.log("" + id + " 处的初始值是 " + clickedItems[id - 1] + " 数组是 " + clickedItems)clickedItems[id - 1] = !clickedItems[id - 1];console.log(clickedItems);设置打开(!打开)}返回 (<侧边栏容器><侧边栏菜单><菜单标志>仪表盘</MenuLogo>{dashboardItems.map((postData) => {返回(<div 键 = {postData.id} ><侧边栏菜单项onClick={() =>处理点击(postData.id)}><SidebarMenuItemLabel>{postData.title}</SidebarMenuItemLabel></SidebarMenuItem><Collapse in={open}>a <div key={postData.id} id="example-collapse-text" className="collapsedText">{postData.text}
</收起>
);})}</SidebarMenu></SidebarContainer>);}const SidebarContainer = styled.div`高度:100vh;宽度:270px;背景颜色:#252529;颜色:#fff;显示:弹性;弹性方向:列;字体系列:Roboto",无衬线;`;const SidebarMenu = styled.ul`显示:弹性;对齐项目:左;弹性方向:列;列表样式:无;宽度:100%;填充左:0px;`;const MenuLogo = styled.div`显示:弹性;对齐项目:居中;对齐内容:开始;间隙:16px;字体大小:18px;行高:1.5;字体粗细:600;高度:45px;颜色:#fff;边距:30px 30px 30px 30px;填充底部:20px;边框底部:1px 实心 #2e2e33;`;const SidebarMenuItem = styled.li`显示:弹性;高度:40px;宽度:100%;对齐项目:居中;padding-left: 30px;&:悬停{背景:rgba(255, 255, 255, 0.05);框阴影:插入 3px 0 0 0 #ffffff;光标:指针;}`;const SidebarMenuItemLabel = styled.p`font-family: "Open Sans", sans-serif;颜色:#fff;字体大小:16px;字体粗细:600;行高:1.3;文本对齐:左;填充:15px 0px;左边距:15px;边距顶部:15px;颜色:#ffffff;`;导出默认侧边栏;
如果您知道解决方案,请告诉我.谢谢!
你的open"变量应该是一个空对象.
const [open, setOpen] = React.useState({});
然后在 handleClick 函数上创建一个以id"为键的新字段.
function handleClick(id) {setOpen((prevState => ({...prevState, [id]: !prevState[id]}))}
然后将其用作打开"道具.
<Collapse in={open[postData.id]}><div key={postData.id} id="example-collapse-text" className="collapsedText">{postData.text}
</收起>
请记住,当您想要访问实际状态时,您总是希望这样做:
const [state, setState] = useState(true)setState(prevState => !prevState)
从来没有
const [state, setState] = useState(true)setState(!state)//<-- 这很糟糕
I'm trying to create a dynamic menu using React and I'm struggling to implement the collapse functionality. I start by mapping each MenuItem using a Json object which works fine. Afterwards, when I tried to implement a collapse functionality when clicked on, all the menuitems collapse instead of just the one that is clicked on. I tried implementing an array which toggles between true/false but I'm having trouble accessing the value when clicked upon. Here is the code:
import React, { Component } from "react";
import styled from "styled-components";
import "./sidebar.css";
import Collapse from 'react-bootstrap/Collapse'
const dashboardItems = [
{
id: 1,
title: "Dashboard",
subtitles: ["Analysis", "Monitor", "Workpplace"],
text: "Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident."
},
{
id: 2,
title: "Form",
subtitles: ["Basic Form", "Step Form", "Advanced Form"],
text: "enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident."
},
{
id: 3,
title: "List",
subtitles: ["Search Table", "Basic List", "Card List"],
text: "richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident."
},
{
id: 4,
title: "Profile",
subtitles: ["Basic Profile", "Advanced Profile"],
text: "Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident."
},
{
id: 5,
title: "Result",
subtitles: ["Success", "Failure"],
text: "craft beer labore wes anderson cred nesciunt sapiente ea proident."
},
{
id: 6,
title: "Account",
subtitles: ["Account Center", "Account Settings"],
text: "wes anderson cred nesciunt sapiente ea proident."
}
];
function Sidebar(){
const [open, setOpen] = React.useState(false);
const [clickedItems, setClickedItems] = React.useState( [false, false, false, false, false, false] );
function handleClick(id) {
console.log("initial value at " + id + " is " + clickedItems[id - 1] + " array is " + clickedItems)
clickedItems[id - 1] = !clickedItems[id - 1];
console.log(clickedItems);
setOpen(!open)
}
return (
<SidebarContainer>
<SidebarMenu>
<MenuLogo>
Dashboard
</MenuLogo>
{dashboardItems.map((postData) => {
return(
<div key = {postData.id} >
<SidebarMenuItem
onClick={() => handleClick(postData.id)}
>
<SidebarMenuItemLabel>{postData.title}</SidebarMenuItemLabel>
</SidebarMenuItem>
<Collapse in={open}>
a <div key={postData.id} id="example-collapse-text" className="collapsedText">
{postData.text}
</div>
</Collapse>
</div>
);
})}
</SidebarMenu>
</SidebarContainer>
);
}
const SidebarContainer = styled.div`
height: 100vh;
width: 270px;
background-color: #252529;
color: #fff;
display: flex;
flex-direction: column;
font-family: "Roboto", sans-serif;
`;
const SidebarMenu = styled.ul`
display: flex;
align-items: left;
flex-direction: column;
list-style: none;
width: 100%;
padding-left: 0px;
`;
const MenuLogo = styled.div`
display: flex;
align-items: center;
justify-content: start;
gap: 16px;
font-size: 18px;
line-height: 1.5;
font-weight: 600;
height: 45px;
color: #fff;
margin: 30px 30px 30px 30px;
padding-bottom: 20px;
border-bottom: 1px solid #2e2e33;
`;
const SidebarMenuItem = styled.li`
display: flex;
height: 40px;
width: 100%;
align-items: center;
padding-left: 30px;
&:hover {
background: rgba(255, 255, 255, 0.05);
box-shadow: inset 3px 0 0 0 #ffffff;
cursor: pointer;
}
`;
const SidebarMenuItemLabel = styled.p`
font-family: "Open Sans", sans-serif;
color: #fff;
font-size: 16px;
font-weight: 600;
line-height: 1.3;
text-align: left;
padding: 15px 0px;
margin-left: 15px;
margin-top: 15px;
color: #ffffff;
`;
export default Sidebar;
Please let me know if you might know of a solution. Thanks!
Your "open" variable should be an empty object.
const [open, setOpen] = React.useState({});
Then on the handleClick function you create a new field that has "id" as key.
function handleClick(id) {
setOpen((prevState => ({...prevState, [id]: !prevState[id]}))
}
Then use that as the "open" prop.
<Collapse in={open[postData.id]}>
<div key={postData.id} id="example-collapse-text" className="collapsedText">
{postData.text}
</div>
</Collapse>
Keep in mind that when you want to access the actual state, you always want to do this:
const [state, setState] = useState(true)
setState(prevState => !prevState)
And never
const [state, setState] = useState(true)
setState(!state) // <-- THIS IS BAD
这篇关于使用 React 和 map 时如何只折叠一个 div的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!