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

如何解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:24:22