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

React中map渲染列表点击时仅控制被点击div显隐

问题根因

当前展开/收起状态定义在UserBlock父组件层级,是所有渲染卡片共享的单一全局状态:所有卡片的详情区显隐、按钮文案都绑定这同一个状态值,点击任意按钮修改状态时,所有卡片都会同步重新渲染、响应同一个状态变化,自然会出现全部同步展开/收起的问题。

修复方法

最简洁的实现是把单张用户卡片抽为独立组件,让每个卡片维护自己的展开状态,互相完全隔离。修复后完整代码如下:

import React, { useState } from 'react'

// 抽离单张用户卡片组件,每个实例独立维护自己的展开状态
const UserCard = ({ user, index }) => {
  const infoTitle = `font-bold`
  const [isExpanded, setIsExpanded] = useState(false)

  const toggleExpand = () => {
    setIsExpanded(prev => !prev)
  }

  return (
    <div className="bg-gray-900 text-white m-2 p-10 w-full rounded-2xl shadow-lg m-8 md:w-1/4 lg:w-1/6">
      <p className={`${infoTitle} text-xl`}>username: {user.name}</p>
      {/* 直接根据当前卡片的isExpanded状态控制显隐 */}
      {isExpanded && (
        <div>
          <p className={infoTitle}>email: {user.email}</p>
          <p className={infoTitle}>website: {user.website}</p>
          <p className={infoTitle}>phone: {user.phone}</p>
          <p className={infoTitle}>address:</p>
          <p className={infoTitle}>suite: {user.address.suite}</p>
          <p className={infoTitle}>street: {user.address.street}</p>
          <p className={infoTitle}>city: {user.address.city}</p>
          <p className={infoTitle}>zipcode: {user.address.zipcode}</p>
        </div>
      )}
      <div>
        <button onClick={toggleExpand}>
          View {isExpanded ? "Less" : "More"}
        </button>
      </div>
    </div>
  )
}

const UserBlock = (props) => {
  return (
    <div className='flex flex-wrap w-full justify-center '>
      {props.userArray.map((user, index) => (
        <UserCard key={index} user={user} index={index} />
      ))}
    </div>
  )
}
export default UserBlock
优化点说明
  • 移除了冗余的viewMoreClass状态:直接通过当前卡片的展开状态判断是否渲染详情区,不需要额外维护class字符串,逻辑更简洁
  • 修正原代码拼写错误:将语义模糊、拼写错误的laodMoreClicked改为更易读的isExpanded
  • 状态更新采用函数式写法setIsExpanded(prev => !prev),避免闭包导致的状态值不同步问题
  • 移除了按钮文案里多余的索引拼接,符合常规交互的文案逻辑

如果你不想抽离额外组件,也可以在父组件用集合存储展开的卡片索引,核心逻辑参考:

const [expandedIndexSet, setExpandedIndexSet] = useState(new Set())
const toggleExpand = (index) => {
  setExpandedIndexSet(prev => {
    const newSet = new Set(prev)
    newSet.has(index) ? newSet.delete(index) : newSet.add(index)
    return newSet
  })
}
// 渲染时判断 expandedIndexSet.has(index) 控制详情显隐,按钮点击传入对应index即可
// 这种方案更适合需要从父组件外部控制卡片展开状态的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:15:59