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

Nextjs报错:Text content does not match server-rendered HTML 修复咨询

修复Next.js中react-countdown的"Text content does not match server-rendered HTML"错误

问题原因

服务端渲染时,API返回的ISO时间字符串(如2022-12-25T11:22:37.000Z)在服务端和客户端的解析结果可能存在差异(比如时区处理、时间解析工具的逻辑差异),导致react-countdown渲染的倒计时文本在服务端生成的HTML和客户端hydrate后的内容不一致,触发Next.js的内容一致性校验错误。而使用Date.now() + 1000 * 60 * 60时,因为是基于当前时间的相对值,组件渲染时的倒计时差值在服务端和客户端计算后初始展示一致,所以未触发错误。

修复方案

方案1:统一时间解析逻辑,确保服务端和客户端结果一致

使用UTC模式解析时间字符串,避免时区干扰,确保服务端和客户端生成完全相同的时间戳:

import React from 'react'
import { Box } from '@mui/material'
import { IFlashBanner } from '../../../interface/flashBanner'
import Countdown from 'react-countdown'
import moment from 'moment'

const FloatingFlashSale = ({
  id,
  title,
  dicount,
  countdownTime,
  image,
}: IFlashBanner) => {
  // 使用moment.utc强制以UTC解析时间字符串,避免时区差异
  const targetTime = moment.utc(countdownTime).valueOf()
  // 也可以用原生Date的UTC解析:
  // const targetTime = Date.parse(countdownTime)

  return (
    <Box
      display="flex"
      sx={{
        backgroundImage: `url(${image})`,
        backgroundSize: '100%',
        backgroundRepeat: 'no-repeat',
      }}
    >
      <Countdown date={targetTime} />
    </Box>
  )
}

export default FloatingFlashSale

方案2:禁用组件的服务端渲染

通过Next.js的dynamic导入,让react-countdown组件只在客户端渲染,彻底避免服务端和客户端的HTML差异:

import React from 'react'
import { Box } from '@mui/material'
import { IFlashBanner } from '../../../interface/flashBanner'
import dynamic from 'next/dynamic'

// 动态导入react-countdown,禁用SSR
const Countdown = dynamic(() => import('react-countdown'), { ssr: false })

const FloatingFlashSale = ({
  id,
  title,
  dicount,
  countdownTime,
  image,
}: IFlashBanner) => {
  const targetTime = new Date(countdownTime).valueOf()

  return (
    <Box
      display="flex"
      sx={{
        backgroundImage: `url(${image})`,
        backgroundSize: '100%',
        backgroundRepeat: 'no-repeat',
      }}
    >
      <Countdown date={targetTime} />
    </Box>
  )
}

export default FloatingFlashSale

方案3:在客户端挂载后再初始化倒计时

使用useState和useEffect,等待客户端挂载后再设置目标时间,避免服务端渲染时的时间差异:

import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import { IFlashBanner } from '../../../interface/flashBanner'
import Countdown from 'react-countdown'

const FloatingFlashSale = ({
  id,
  title,
  dicount,
  countdownTime,
  image,
}: IFlashBanner) => {
  const [targetTime, setTargetTime] = useState<number | null>(null)

  useEffect(() => {
    // 客户端挂载后再解析时间
    setTargetTime(new Date(countdownTime).valueOf())
  }, [countdownTime])

  // 未初始化时可以展示加载状态
  if (!targetTime) return null

  return (
    <Box
      display="flex"
      sx={{
        backgroundImage: `url(${image})`,
        backgroundSize: '100%',
        backgroundRepeat: 'no-repeat',
      }}
    >
      <Countdown date={targetTime} />
    </Box>
  )
}

export default FloatingFlashSale

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:00:47