如何解决Next.js中使用WordPress API时的React Hydration错误
解决Next.js中React Hydration错误的方案
你的react-hydration-error问题大概率是服务端渲染的HTML与客户端hydrate生成的DOM结构不匹配导致的,结合你的代码,这里给出几个针对性修复方案:
1. 直接使用props而非复制到state
你在constructor中将props.bloglist复制到state,但类组件中props更新时state不会自动同步,这可能导致服务端和客户端的数据不一致。直接使用props即可:
// 移除constructor中的state赋值,直接在render里用props.bloglist render() { const { bloglist } = this.props; if (!bloglist) { return <div className="container blog-section"><div className="row"><p>Loading...</p></div></div>; // 替换null为加载状态,避免渲染空内容导致不匹配 } // ... 后续代码用bloglist替代this.state.data }
2. 替换ReactHtmlParser为dangerouslySetInnerHTML
ReactHtmlParser将HTML字符串转换为React元素的过程,在服务端和客户端可能产生细微差异,而dangerouslySetInnerHTML是React原生处理HTML字符串的方式,更稳定,能减少hydration不匹配:
// 替换原来的ReactHtmlParser行 <p className="expert" dangerouslySetInnerHTML={{ __html: x.excerpt.rendered }}></p>
注意:确保x.excerpt.rendered是可信的HTML内容,避免XSS风险。
3. 统一服务端与客户端的数据
如果bloglist是通过getServerSideProps或getStaticProps获取的,要保证客户端hydrate时的数据与服务端完全一致,避免在客户端额外修改数据导致DOM结构差异。
修改后的完整代码示例
import Image from 'next/image'; import React, { Component } from 'react'; import Link from 'next/link'; import { BiCalendar } from 'react-icons/bi'; export default class Blog extends Component { render() { const { bloglist } = this.props; if (!bloglist) { return <div className="container blog-section"><div className="row"><p>Loading...</p></div></div>; } return ( <> <div className="container blog-section"> <div className="row"> <h2>Latest Posts</h2> </div> <div className="row"> {bloglist.map((x) => ( <div className="col-md-4 boxs text-center" key={x.id}> {/* 用x.id作为key,比索引更稳定 */} <div className="bg-info"> <img src={x.images.large} className="img-fluid" alt={x.title.rendered} /> <h3 dangerouslySetInnerHTML={{ __html: x.title.rendered }}></h3> {/* 如果标题也是HTML格式,同样用这个方式 */} <p className="shopping"> <span> <BiCalendar /> {x.date} </span> </p> <p className="expert" dangerouslySetInnerHTML={{ __html: x.excerpt.rendered }}></p> <Link href={`/blog/${x.slug}/${x.id}`}> <p className="readmore"> <span>Readmore</span> </p> </Link> </div> </div> ))} </div> </div> </> ); } }
额外细节补充:
- 用
x.id作为列表项的key,比索引更稳定,避免列表更新时的DOM复用问题。 - 如果
x.title.rendered包含HTML格式(比如加粗、链接),同样用dangerouslySetInnerHTML处理,避免文本转义导致的结构差异。
内容的提问来源于stack exchange,提问作者siva
相关产品推荐
相关产品推荐

