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

如何通过onClick控制映射列表中对应ul元素的显示状态?

解决方案

核心思路

不用给每个元素单独加state,用一个统一的state来记录哪些项是展开状态——你已经用obj.name作为每个项的唯一key,刚好可以用它来标识每个需要切换的项。


两种实用实现方案

方案1:单次仅展开一个项(点击新项自动收起旧项)

适合需要互斥展开的场景:

import { useState } from 'react';

function YourComponent() {
  // 存储当前展开的项名称,初始为null表示全部收起
  const [expandedItem, setExpandedItem] = useState(null);
  // 假设myData是从API获取的数组数据

  return (
    <div>
      {myData.map((obj) => (
        <div style={{ maxWidth: "500px", marginLeft: "25%" }} key={obj.name}>
          <img src={obj.image} width="500px" alt={obj.name} />
          <h1>{obj.name}</h1>
          <h2 
            onClick={() => {
              // 切换逻辑:当前项已展开就收起,否则展开;点击其他项自动替换当前展开项
              setExpandedItem(prev => prev === obj.name ? null : obj.name);
            }}
            style={{ cursor: 'pointer' }} // 加鼠标样式提示可点击
          >
            Ingredients
          </h2>
          {/* 根据state判断是否显示ul */}
          <ul style={{ display: expandedItem === obj.name ? 'block' : 'none' }}>
            {obj.ingredients.map((ingredient, idx) => (
              {/* 用唯一且稳定的key,别用Math.random() */}
              <li key={`${obj.name}-ing-${idx}`}>{ingredient}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

方案2:支持同时展开多个项

如果需要多个ul同时显示,用Set存储所有展开的项名称:

import { useState } from 'react';

function YourComponent() {
  // 用Set存储所有展开的项名称,初始为空表示全部收起
  const [expandedItems, setExpandedItems] = useState(new Set());

  // 抽离切换逻辑,代码更整洁
  const toggleExpand = (itemName) => {
    setExpandedItems(prev => {
      const newSet = new Set(prev);
      newSet.has(itemName) ? newSet.delete(itemName) : newSet.add(itemName);
      return newSet;
    });
  };

  return (
    <div>
      {myData.map((obj) => (
        <div style={{ maxWidth: "500px", marginLeft: "25%" }} key={obj.name}>
          <img src={obj.image} width="500px" alt={obj.name} />
          <h1>{obj.name}</h1>
          <h2 
            onClick={() => toggleExpand(obj.name)}
            style={{ cursor: 'pointer' }}
          >
            Ingredients
          </h2>
          <ul style={{ display: expandedItems.has(obj.name) ? 'block' : 'none' }}>
            {obj.ingredients.map((ingredient, idx) => (
              <li key={`${obj.name}-ing-${idx}`}>{ingredient}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

关键注意点

  • 别用Math.random()生成key,每次渲染都会生成新值,会导致组件频繁重渲染甚至丢失状态,用obj.name+索引的组合足够唯一且稳定
  • 默认隐藏ul的逻辑通过初始state(null或空Set)配合display: none实现,无需额外处理
  • 可以根据需求给h2加展开/收起的文字提示(比如Ingredients ▼/Ingredients ▲),提升交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:30:52