如何修复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
相关产品推荐
相关产品推荐

