React循环渲染时如何基于索引为点击选中项单独应用CSS样式
问题原因
你当前使用全局单一布尔值isBarOpen作为所有列表项的样式判断依据,所有列表项共享同一个状态,点击任意项修改状态后,所有项都会读取到同一个激活值,因此会同步套用激活样式。
实现方案
核心逻辑是将「全局布尔状态」替换为「存储当前选中项标识的状态」,渲染每一项时单独判断当前项是否为选中项,单独生成对应样式:
- 初始化状态存储选中项的索引/唯一业务ID,默认值设为
null表示初始无选中项 - 遍历渲染列表时,逐次判断当前项的标识是否与状态中存储的选中标识一致,将判断结果传入样式生成方法
- 点击列表项时,将当前项的标识更新到状态中,即可实现仅选中项套用激活样式
修改后代码
组件状态与渲染逻辑
// 替换原有的isBarOpen布尔状态,存储当前选中的票务索引,默认无选中 const [selectedTicketIndex, setSelectedTicketIndex] = useState(null); // 列表遍历渲染(替换原有的map逻辑) {ticketList.map((ticket, i) => { // 单独判断当前项是否为选中项,生成当前项专属样式 const isBarOpen = selectedTicketIndex === i; const classes = getStyles.new_ticketSearch({ isBarOpen })(); return ( <Box className={classes.bookingTicketContainer} onClick={() => { handleOnSelectTicket(i); // 点击同一项可取消选中,若需要点击后固定选中不取消,直接写setSelectedTicketIndex(i)即可 setSelectedTicketIndex(selectedTicketIndex === i ? null : i); }} > <Box className={classes.bookingBar}> <Box className={classes.bookingSubBox}> <Box className={classes.barInfoboxN1}> <Typography className={classes.durationDetails}>{ticket.ticketsOverview[1]}</Typography> </Box> <Box className={classes.barInfoBoxN2}> <Typography className={classes.changesDetails}>N/A</Typography> </Box> <Box className={classes.barInfoboxN3}> <Typography className={classes.transportModeDetails}> {ticket.ticketsOverview[8]} </Typography> </Box> <Box className={classes.barInfoboxN4}> <Typography className={classes.priceDetails}> {ticket.ticketsOverview[3]} {ticket.ticketsOverview[4]} {ticket.ticketsOverview[5]} </Typography> </Box> </Box> </Box> </Box> ) })}
样式代码
原有JSS样式逻辑无需修改,会根据每一项单独传入的isBarOpen值自动生成对应样式:
bookingBar: { display: "flex", width: 751, height: 76, background: !isBarOpen ? theme.palette.common.white : theme.palette.primary[500], color: isBarOpen && theme.palette.common.white, boxShadow: "0px 2px 2px 1px rgba(0, 0, 0, 0.12), 0px 2px 6px 2px rgba(0, 0, 0, 0.08)", borderRadius: 5, },
优化提示
- 若列表数据存在动态增删、排序的场景,不要用索引作为选中标识,优先用票务数据本身的唯一ID(比如
ticketId)存储选中状态,避免索引错位导致样式异常 - 若需要支持多选,可将状态改为数组类型,存储所有选中项的标识,判断选中时用
selectedIdList.includes(currentItemId)即可
内容的提问来源于stack exchange,提问作者Sudhir
相关产品推荐
相关产品推荐

