You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React映射渲染组件列表时如何设置并保持选中Active状态

实现方案

你当前已经给每个列表项配置了唯一的key={job.id},直接用接口返回的job.id作为选中项的标识即可,不需要额外使用数组索引——用数据本身的唯一ID做标识比数组索引稳定得多,后续列表做排序、过滤、增删操作时都不会出现选中状态错位的问题。

步骤1:在父组件维护全局选中状态

不要把选中状态分散存在每个JobCard内部,统一放在父组件管理,避免重渲染时状态错乱。
首先在父组件引入useState存储当前选中的职位ID:

import { useState } from 'react';

// 父组件内
const [selectedJobId, setSelectedJobId] = useState(null);

修改列表遍历的渲染逻辑,给每个子组件传入选中状态标记和选中回调:

{
  jobs.length > 0 && 
  jobs.map(
    (job) => 
    <JobCard 
      key={job.id} 
      job={job}
      isSelected={selectedJobId === job.id}
      onSelect={() => setSelectedJobId(job.id)}
    />
  )
}

如果需要支持多选,把state改成存储ID集合即可:const [selectedJobIds, setSelectedJobIds] = useState(new Set()),选中逻辑改为点击时切换集合内对应ID的存在状态,子组件的选中判断改为selectedJobIds.has(job.id)。

步骤2:修改JobCard子组件,绑定选中交互和样式

子组件接收新增的isSelected、onSelect两个props,给卡片根容器绑定点击事件,根据选中状态动态切换蓝色样式;注意收藏按钮的点击事件要阻止冒泡,避免点收藏时误触发卡片选中。
修改后的JobCard代码如下:

import { useState } from 'react';

const JobCard = ({ job, isSelected, onSelect }) => {
  const [open, setOpen] = useState(false)
  const responseAdjusted = job.category.label
  const responseArray = responseAdjusted.split(" ")[0]

  return (
      <CardContainer
        onClick={onSelect}
        sx={{
          backgroundColor: isSelected ? '#1976d2' : '#fff', // 可替换为项目内对应的蓝色色值
          cursor: 'pointer',
          // 可在此处补充其他选中态样式,比如边框高亮、阴影变化等
        }}
      >
        <CardPrimary>
          <CardHeader>
            <CardHeaderTopRow>
              <Typography variant = "cardheader1">
                {job.title}
              </Typography>
              <HeartDiv>
                <IconButton 
                  color={open ? "error" : "buttoncol"} 
                  sx={{ boxShadow: 3}} 
                  fontSize ="2px" 
                  size="small"
                  onClick={(e) => {
                    e.stopPropagation(); // 阻止事件冒泡到卡片容器
                    setOpen(prevOpen => !prevOpen)
                  }}
                >
                  <FavoriteIcon fontSize="inherit" />
                </IconButton>
              </HeartDiv>

            </CardHeaderTopRow>
            <Typography variant = "subtitle4" color="text.secondary">
              {job.company.display_name}  
            </Typography>
          </CardHeader>

          <CardSecondary>
          </CardSecondary>
        </CardPrimary>
      </CardContainer>
  )
}

export default JobCard

关键注意事项

  • 禁止使用数组索引作为选中项标识:列表排序、过滤、增删数据时索引会动态变化,会导致选中状态和实际卡片错位。
  • 不要在子组件内部维护选中状态:列表重渲染时子组件可能被复用或销毁,内部状态无法和列表数据保持同步,放在父组件统一管理是最可靠的方案。
  • 如果需要点击已选中卡片取消选中,把父组件的onSelect逻辑改成setSelectedJobId(prev => prev === job.id ? null : job.id)即可。

内容的提问来源于stack exchange,提问作者n_d22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:36:32