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

Next.js 13下拉框选择控制表格显示及报错解决

Next.js 13 下拉框筛选表格解决方案

问题根源

  1. 你的组件默认是服务器组件,可以用async/await读取本地JSON文件,但不能使用客户端交互API(比如useState、onChange事件)
  2. 当你给组件加上'use client'后,fetchJson里的fs模块会报错——因为fs是Node.js服务器端模块,浏览器环境根本没有这个API

解决思路:拆分组件

把数据获取和UI交互拆成两个独立组件:

  • 服务器组件:只负责读取本地JSON数据、解析校验,然后把数据传递给客户端组件
  • 客户端组件:只处理下拉框选中状态、表格条件渲染,完全在浏览器端运行,不碰任何服务器端API

完整代码实现

1. 修改原服务器组件(DashboardContentSection.tsx)

import { fetchJson } from '@/lib/util/fetchJson';
import { Dashboard, dashboard, ProjectServices } from '@/schema/api';
import DashboardFilteredTable from './DashboardFilteredTable';

export default async function DashboardContentSection({ path }: { path: string }) {
  // 服务器端读取并解析数据
  const dashboardData = await fetchJson<Dashboard>(`/${path}/data.json`);
  const projectsData = await fetchJson<ProjectServices>(`/deploy.json`);
  const parsedDashboardData = dashboard.parse(dashboardData).data;

  // 把数据传给客户端组件
  return (
    <div>
      <DashboardFilteredTable 
        projects={projectsData.apps}
        dashboardData={parsedDashboardData}
      />
    </div>
  );
}

2. 创建客户端组件(DashboardFilteredTable.tsx)

'use client';

import { useState } from 'react';

// 定义props类型
interface Props {
  projects: string[];
  dashboardData: {
    cluster: string;
    project: string;
    version: Array<{ version: string; percentage: number }>;
  }[];
}

export default function DashboardFilteredTable({ projects, dashboardData }: Props) {
  // 管理选中的项目状态
  const [selectedProject, setSelectedProject] = useState<string>(projects[0] || '');

  // 根据选中项目过滤表格数据
  const filteredData = selectedProject 
    ? dashboardData.filter(item => item.project === selectedProject)
    : dashboardData;

  return (
    <>
      <select 
        className='w-full p-2'
        value={selectedProject}
        onChange={(e) => setSelectedProject(e.target.value)}
      >
        {projects.map((project, index) => (
          <option key={index} value={project}>
            {project}
          </option>
        ))}
      </select>
      <table className='w-full text-left'>
        <thead className='bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-400'>
          <tr>
            <th scope='col' className='px-6 py-3'>Cluster</th>
            <th scope='col' className='px-6 py-3'>Project</th>
            <th scope='col' className='px-6 py-3'>Version</th>
            <th scope='col' className='px-6 py-3'>Traffic</th>
          </tr>
        </thead>
        <tbody>
          {filteredData.map((i) => (
            <tr
              className='cursor-pointer border-b bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-600'
              key={i.cluster}
            >
              <td className='px-6 py-3'>{i.cluster}</td>
              <td className='px-6 py-3'>{i.project}</td>
              {i.version[0] && (
                <>
                  <td key={i.version[0].version} className='px-6 py-3'>{i.version[0].version}</td>
                  <td className='px-6 py-3'>{i.version[0].percentage}%</td>
                </>
              )}
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
}

关键说明

  • 服务器组件保留了fetchJson调用,因为fs只能在服务器端运行,不会触发报错
  • 客户端组件通过useState管理选中状态,onChange事件正常工作,所有交互逻辑都在浏览器端完成
  • 数据通过props从服务器组件传递到客户端组件,符合Next.js 13的组件模型规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 14:47:03