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

在Next.js中使用typewriter-effect库触发Hydration失败求助

Next.js中使用typewriter-effect出现Hydration失败错误的解决办法

问题描述

使用typewriter-effect库时遇到如下错误:

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

尝试通过useEffect将Typewriter存入状态修复,但未生效。相关代码如下:

TypeEffect.tsx

import Typewriter from 'typewriter-effect';

const TypeEffect = () => {
  const strings = [
    'modern & innovative digital solutions.',
    'e-commerces, web systems, landing pages, blogs & much more.',
    'front-end & back-end development.',
    'UX &UI best pratices.',
  ];

  return (
    <Typewriter
      options={{
        autoStart: true,
        loop: true,
      }}
      onInit={(typewriter) => {
        typewriter
          .typeString(strings[0])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[1])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[2])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[3])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .start();
      }}
    />
  );
};

export default TypeEffect;

Content.tsx

import React from 'react';
import TypeEffect from '../TypeEffect';

const Content = () => {
  return (
    <main className='mx-auto px-2 select-none font-anton md:-translate-y-24 md:-translate-x-24'>
      <h1 className='text-6xl md:text-7xl mb-4'>
        creative developer
        <span className='text-primary'>.</span>
      </h1>

      <p className='font-montserrat absolute font-regular md:text-2xl'>
        {TypeEffect()}
      </p>
    </main>
  );
};

export default Content;

错误原因

  1. 组件调用方式错误:在Content.tsx中直接用{TypeEffect()}是函数调用,不是React组件的正确渲染方式,会导致服务端和客户端的渲染逻辑不一致。
  2. 服务端渲染不兼容:typewriter-effect依赖浏览器DOM执行打字动画,服务端渲染时无法运行这些逻辑,导致初始渲染的空内容和客户端hydrate后的内容不匹配,触发Hydration错误。

解决办法

步骤1:修正组件渲染方式

把Content.tsx中的{TypeEffect()}改成组件标签形式:

<p className='font-montserrat absolute font-regular md:text-2xl'>
  <TypeEffect />
</p>

步骤2:禁用TypeEffect的服务端渲染

有两种方式实现,选其一即可:

方式一:使用Next.js dynamic导入(推荐)

修改Content.tsx中的导入逻辑,禁用SSR:

import React from 'react';
import dynamic from 'next/dynamic';

// 禁用服务端渲染
const TypeEffect = dynamic(() => import('../TypeEffect'), { ssr: false });

const Content = () => {
  return (
    <main className='mx-auto px-2 select-none font-anton md:-translate-y-24 md:-translate-x-24'>
      <h1 className='text-6xl md:text-7xl mb-4'>
        creative developer
        <span className='text-primary'>.</span>
      </h1>

      <p className='font-montserrat absolute font-regular md:text-2xl'>
        <TypeEffect />
      </p>
    </main>
  );
};

export default Content;

方式二:在TypeEffect组件中控制客户端渲染

修改TypeEffect.tsx,通过状态确保仅在客户端加载后渲染Typewriter:

import { useEffect, useState } from 'react';
import Typewriter from 'typewriter-effect';

const TypeEffect = () => {
  const [isClient, setIsClient] = useState(false);
  const strings = [
    'modern & innovative digital solutions.',
    'e-commerces, web systems, landing pages, blogs & much more.',
    'front-end & back-end development.',
    'UX &UI best pratices.',
  ];

  useEffect(() => {
    // 组件挂载后标记为客户端环境
    setIsClient(true);
  }, []);

  // 服务端渲染时返回空,避免内容不匹配
  if (!isClient) return null;

  return (
    <Typewriter
      options={{
        autoStart: true,
        loop: true,
      }}
      onInit={(typewriter) => {
        typewriter
          .typeString(strings[0])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[1])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[2])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .typeString(strings[3])
          .pauseFor(4000)
          .deleteAll()
          .pauseFor(2000)
          .start();
      }}
    />
  );
};

export default TypeEffect;

为什么之前的尝试无效

之前仅用useEffect存储Typewriter实例,但没解决组件调用方式错误和服务端与客户端渲染内容不匹配这两个核心问题,所以错误依然存在。


内容的提问来源于stack exchange,提问作者undefined-mind

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:25:30