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

如何在Next.js表格中实现点击按钮仅显示对应行详情

解决Next.js中行详情独立显示/隐藏的问题

问题根源在于你用了单个布尔状态变量(isVisible1/isVisible2)控制所有行的详情显示,所有行共用同一个状态,所以点击任意按钮都会触发所有行的状态改变。要实现每行独立控制,需要给每行分配专属的状态记录。

具体修改步骤:

  1. 替换状态定义
    把原来的单个布尔状态改成对象,用来存储每个公告ID对应的显示状态:
// 用对象存储每个announcement的显示状态,键为ads_id,值为布尔值
const [visibleDetails, setVisibleDetails] = useState({});
const [visibleOrders, setVisibleOrders] = useState({});
  1. 修改切换函数
    让切换函数接收当前行的ID作为参数,只修改对应ID的状态:
const toggleDetails = (adsId) => {
  setVisibleDetails(prev => ({
    ...prev,
    [adsId]: !prev[adsId] // 切换对应ID的显示状态,默认未定义时为false
  }));
};

const toggleOrders = (adsId) => {
  setVisibleOrders(prev => ({
    ...prev,
    [adsId]: !prev[adsId]
  }));
};
  1. 修改按钮与渲染逻辑
    在渲染每行时,把当前公告的ads_id传给按钮的点击事件,并且根据visibleDetails中对应ID的值来决定是否显示详情:
// 假设这是你渲染每行的外层map
{announcements.map(announcement => (
  <tr key={announcement.ads_id}>
    {/* 其他行内容 */}
    <button 
      className="h-10 px-4 ..." 
      onClick={() => toggleDetails(announcement.ads_id)}
    >
      详情按钮
    </button>
    <button 
      className="h-10 px-4 ..." 
      onClick={() => toggleOrders(announcement.ads_id)}
    >
      订单按钮
    </button>

    {/* 控制详情表格显示 */}
    {visibleDetails[announcement.ads_id] && (
      <table>
        <thead className="bg-slate-300">
          <th className="p-3 text-sm ...">id</th>
          <th className="p-3 text-sm ...">Data</th>
        </thead>
        <tbody>
          {/* 嵌套渲染详情 */}
          {announcement.order_details.map(detail => (
            <tr key={detail.id}>
              <td>{detail.name}</td>
              {/* 其他详情列 */}
            </tr>
          ))}
        </tbody>
      </table>
    )}
  </tr>
))}

核心逻辑说明

  • 用对象visibleDetails记录每一行的显示状态,每个键对应唯一的ads_id,确保每行状态独立。
  • 点击按钮时,只更新当前行ID对应的状态值,不会影响其他行。
  • 渲染详情时,只根据当前行ID对应的状态判断是否显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:22:56