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

Next.js SSR环境下Embla Carousel无法正常工作的问题

解决Next.js SSR下Embla Carousel无法正常运行的问题

Embla Carousel依赖浏览器DOM及相关API,Next.js SSR时组件会先在服务端渲染,此时没有浏览器环境,导致Embla初始化失败。后续客户端hydrate时,之前生成的无效实例无法正常工作,但重新保存触发纯客户端渲染时,Embla能获取正常的浏览器环境,因此可以正常运行。下面给出两种可行的解决方案:

方案一:动态导入组件并禁用SSR

将包含Embla Carousel的组件通过Next.js的dynamic导入,明确禁用SSR,确保组件只在客户端渲染:

// 页面或父组件中
import dynamic from 'next/dynamic';

// 动态导入Embla轮播组件,禁用SSR
const EmblaCourseCarousel = dynamic(() => import('./EmblaCourseCarousel'), {
  ssr: false,
});

// 使用组件
export default function YourPage() {
  return (
    <div>
      <EmblaCourseCarousel courses={courses} />
    </div>
  );
}

你的EmblaCourseCarousel组件保持原有逻辑即可,由于它只会在客户端加载,Embla能正常完成初始化。

方案二:在组件内判断客户端环境再初始化

在组件中通过状态控制,确保Embla只在客户端环境下初始化:

import { useState, useEffect } from 'react';
import useEmblaCarousel from 'embla-carousel-react';
import WheelGesturesPlugin from 'embla-carousel-wheel-gestures';
import styles from './your-component.module.css';
import Slide from './Slide';

export default function EmblaCourseCarousel({ courses }) {
  const [isClient, setIsClient] = useState(false);
  // 仅当客户端环境时传入Embla配置和插件
  const [viewportRef, embla] = useEmblaCarousel(
    isClient ? {
      slidesToScroll: 'auto',
      axis: 'y',
      skipSnaps: true,
    } : undefined,
    isClient ? [WheelGesturesPlugin()] : []
  );

  // useEffect仅在客户端执行,标记进入客户端环境
  useEffect(() => {
    setIsClient(true);
  }, []);

  // 客户端环境下重新初始化Embla(确保配置生效)
  useEffect(() => {
    if (!embla || !isClient) return;
    embla.reInit({
      slidesToScroll: 'auto',
      axis: 'y',
      skipSnaps: true,
    });
  }, [embla, isClient]);

  return (
    // 仅客户端环境时绑定viewportRef
    <div ref={isClient ? viewportRef : undefined} className={styles.right_block}>
      <div className={styles.slider}>
        {courses.map((item, index) => (
          <Slide key={index} {...item} />
        ))}
      </div>
    </div>
  );
}

关键说明

  • 服务端渲染时,isClient为false,Embla不会初始化,避免依赖浏览器API报错。
  • 客户端hydrate完成后,useEffect触发setIsClient(true),组件重新渲染,此时Embla在浏览器环境下初始化,能正常工作。
  • viewportRef仅在客户端绑定,避免服务端DOM绑定无效的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:42:57