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

如何修复Next.js 13.4.16表格组件中的Hydration failed错误?

修复Next.js 13.4.16中的Hydration不匹配错误

错误信息

Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.

Warning: Expected server HTML to contain a matching <tr> in <tbody>.

Component Stack
table
section

问题代码

<section className="mt-24 w-full h-full flex justify-center">
  <table className="min-w-max bg-white border border-gray-200 rounded-lg overflow-hidden">
    <thead className="bg-gray-100 text-gray-600 uppercase text-sm leading-normal ">
      <tr className="bg-gray-100 text-gray-600 uppercase text-sm leading-normal">
        <th className=" py-3 px-6 text-left">ID</th>
        <th className=" py-3 px-6 text-left">NAME</th>
        <th className=" py-3 px-6 text-left">ACTION</th>
      </tr>
    </thead>
    <tbody className=" text-gray-600 text-sm font-light">
      {data.todos.map((todo: any) => {
        <tr key={todo.id} className="border-b border-gray-200 hover:bg-gray-100">
          <td className="py-3 px-6">
            {todo.id}
          </td>
          <td className="py-3 px-6">
            {todo.name}
          </td>
          <td className="py-3 px-6">
            <button>DELETE</button>
          </td>
        </tr>
      })};
    </tbody>
  </table>
</section>

修复方案

问题核心是data.todos.map的回调函数没有返回<tr>元素:用大括号{}包裹JSX时,必须显式返回内容,否则map函数会返回undefined,导致服务器渲染时<tbody>内没有任何<tr>,客户端后续渲染时产生UI不匹配,触发Hydration错误。

有两种直接修复方式:

  • 将大括号{}替换为小括号(),箭头函数会自动返回括号内的JSX:
{data.todos.map((todo: any) => (
  <tr key={todo.id} className="border-b border-gray-200 hover:bg-gray-100">
    <td className="py-3 px-6">{todo.id}</td>
    <td className="py-3 px-6">{todo.name}</td>
    <td className="py-3 px-6"><button>DELETE</button></td>
  </tr>
))}
  • 保留大括号,添加return语句返回JSX:
{data.todos.map((todo: any) => {
  return (
    <tr key={todo.id} className="border-b border-gray-200 hover:bg-gray-100">
      <td className="py-3 px-6">{todo.id}</td>
      <td className="py-3 px-6">{todo.name}</td>
      <td className="py-3 px-6"><button>DELETE</button></td>
    </tr>
  )
})}

额外建议:处理data.todos为空的情况,避免map调用报错,同时保持UI一致性:

<tbody className=" text-gray-600 text-sm font-light">
  {data.todos.length === 0 ? (
    <tr>
      <td colSpan={3} className="py-3 px-6 text-center">暂无待办事项</td>
    </tr>
  ) : (
    data.todos.map((todo: any) => (
      <tr key={todo.id} className="border-b border-gray-200 hover:bg-gray-100">
        <td className="py-3 px-6">{todo.id}</td>
        <td className="py-3 px-6">{todo.name}</td>
        <td className="py-3 px-6"><button>DELETE</button></td>
      </tr>
    ))
  )}
</tbody>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:54:54