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

React映射渲染JobCard列表时如何保持选中状态与高亮样式

实现方法

你当前代码里给每个列表项设置的key={job.id}就是最可靠的唯一索引,API返回的岗位id是全局唯一值,不会因为列表排序、增删数据发生变化,完全可以作为选中状态的判定依据,不需要额外生成索引。不要用map遍历的数组下标做标识,否则列表变动时会出现状态错位的问题。

根据你是否需要在父组件获取选中项的数据,有两种实现方式可选:


方案1:父组件统一管理选中状态(推荐)

如果后续需要在父层拿到当前选中的岗位数据做其他逻辑(比如提交选中项、联动其他组件),就把选中状态存在父组件:

  • 父组件新增state存储当前选中的岗位id
  • 给每个JobCard传入两个props:当前项是否选中的布尔值、切换选中状态的回调
  • JobCard根据传入的选中状态控制蓝色高亮样式,点击时触发回调更新父组件state

父组件修改后的代码:

import { useState } from 'react';
// 父组件其他逻辑...
const [selectedJobId, setSelectedJobId] = useState(null);

const toggleSelectJob = (jobId) => {
  // 点击已选中的项则取消选中,否则设为当前选中项
  setSelectedJobId(prev => prev === jobId ? null : jobId);
};

// 列表渲染部分
{
  jobs.length > 0 && 
  jobs.map((job) => (
    <JobCard 
      key={job.id} 
      job={job}
      isSelected={selectedJobId === job.id}
      onToggleSelect={() => toggleSelectJob(job.id)}
    />
  ))
}

JobCard组件修改后的代码:

import { useState } from 'react';

const JobCard = ({ job, isSelected, onToggleSelect }) => {
  const responseAdjusted = job.category.label
  const responseArray = responseAdjusted.split(" ")[0]
  // 原有收藏按钮状态
  const [favoriteOpen, setFavoriteOpen] = useState(false);

  return (
    <CardContainer 
      onClick={onToggleSelect}
      sx={{
        // 按你的设计需求调整选中时的蓝色样式
        border: isSelected ? '2px solid #1976d2' : '1px solid #e0e0e0',
        backgroundColor: isSelected ? '#e3f2fd' : '#fff',
        cursor: 'pointer'
      }}
    >
      <CardPrimary>
        <CardHeader>
          <CardHeaderTopRow>
            <Typography variant = "cardheader1">
              {job.title}
            </Typography>
            <HeartDiv>
              <IconButton 
                color={favoriteOpen ? "error" : "buttoncol"} 
                sx={{ boxShadow: 3}} 
                size="small"
              >
                <FavoriteIcon 
                  fontSize="inherit"
                  onClick={(e) => {
                    // 阻止事件冒泡,避免点击收藏按钮时触发卡片选中
                    e.stopPropagation();
                    setFavoriteOpen(prev => !prev);
                  }}
                />
              </IconButton>
            </HeartDiv>
          </CardHeaderTopRow>
          <Typography variant = "subtitle4" color="text.secondary">
            {job.company.display_name}
          </Typography>
        </CardHeader>
        <CardSecondary></CardSecondary>
      </CardPrimary>
    </CardContainer>
  )
}

方案2:子组件独立管理选中状态

如果不需要父组件感知选中状态,直接把选中状态存在每个JobCard内部即可。React会根据你设置的key={job.id}区分不同的卡片实例,每个实例的状态互相独立,不会出现串状态的问题:

import { useState } from 'react';

const JobCard = ({ job }) => {
  const responseAdjusted = job.category.label
  const responseArray = responseAdjusted.split(" ")[0]
  const [favoriteOpen, setFavoriteOpen] = useState(false);
  // 子组件自己维护选中状态
  const [isSelected, setIsSelected] = useState(false);

  return (
    <CardContainer 
      onClick={() => setIsSelected(prev => !prev)}
      sx={{
        border: isSelected ? '2px solid #1976d2' : '1px solid #e0e0e0',
        backgroundColor: isSelected ? '#e3f2fd' : '#fff',
        cursor: 'pointer'
      }}
    >
      <CardPrimary>
        <CardHeader>
          <CardHeaderTopRow>
            <Typography variant = "cardheader1">
              {job.title}
            </Typography>
            <HeartDiv>
              <IconButton 
                color={favoriteOpen ? "error" : "buttoncol"} 
                sx={{ boxShadow: 3}} 
                size="small"
              >
                <FavoriteIcon 
                  fontSize="inherit"
                  onClick={(e) => {
                    e.stopPropagation();
                    setFavoriteOpen(prev => !prev);
                  }}
                />
              </IconButton>
            </HeartDiv>
          </CardHeaderTopRow>
          <Typography variant = "subtitle4" color="text.secondary">
            {job.company.display_name}
          </Typography>
        </CardHeader>
        <CardSecondary></CardSecondary>
      </CardPrimary>
    </CardContainer>
  )
}

补充说明:如果需要实现多选效果,把方案1里父组件的selectedJobId改成数组类型,存储所有选中的jobId,判断选中时用selectedJobId.includes(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 08:42:28