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

Next.js13使用tiny-slider-react报window未定义错误的解决方法

问题:Next.js 13中使用tiny-slider-react出现window is not defined错误

我用Next.js 13搭建网站,首页通过tiny-slider-react实现产品轮播组件。已经在carousel.js首行添加'use client'指令,并且通过useEffect判断window对象存在后再渲染TinySlider组件,但每次刷新页面和执行npm run build时都会触发ReferenceError: window is not defined错误。

错误信息

刷新页面时:

  • error node_modules\tiny-slider\dist\tiny-slider.js (5:0) @ eval
  • error ReferenceError: window is not defined
  • at webpack_require (F:\Projects\nexjs\decoz.next\server\webpack-runtime.js:33:42)

执行npm run build时:

  • info Collecting page data
  • [ ] - info Generating static pages (0/4)ReferenceError: window is not defined

原代码

"use client";
import TinySlider from "tiny-slider-react";
import CarouselItem from "./carousel-item";
import "tiny-slider/dist/tiny-slider.css";
import { useEffect, useState } from "react";

function Carousel(props) {
  const [mount, setMount] = useState(false);
  const { children } = props;

  useEffect(() => {
    if (typeof window === "object") {
      setMount(true);
    }
  }, [setMount, window]);

  const settings = {
    lazyload: true,
    nav: false,
    mouseDrag: true,
    loop: true,
    items: 1,
    gutter: 20,
    controls: false,
    autoplay: true,
    autoplayHoverPause: true,
    autoplayButtonOutput: false,
    speed: 250,
    autoplayTimeout: 2500,
    responsive: {
      2048: {
        items: 10,
      },
      1920: {
        items: 4,
      },
      1728: {
        items: 4,
      },
      1440: {
        items: 4,
      },
      1280: {
        items: 4,
      },
      1194: {
        items: 4,
      },
      1114: {
        items: 4,
      },
      1180: {
        items: 4,
      },
      1104: {
        items: 4,
      },
      1024: {
        items: 4,
      },
      834: {
        items: 2,
      },
      820: {
        items: 2,
      },
      800: {
        items: 2,
      },
      768: {
        items: 2,
      },
    },
  };

  if (mount) {
    return (
      <TinySlider settings={settings} onInit={() => {}}>
        {props.data.map((item) => (
          <CarouselItem key={item.id} data={item} />
        ))}
      </TinySlider>
    );
  }
  return null;
}

export default Carousel;

package.json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "aos": "^2.3.4",
    "eslint": "8.40.0",
    "eslint-config-next": "13.4.1",
    "next": "13.4.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "tiny-slider-react": "^0.5.7"
  }
}

解决方案

问题核心:即使添加了'use client',Next.js在构建或服务端渲染阶段仍会执行模块导入逻辑,而tiny-slider的源码直接依赖window对象,导致服务端执行时出错。

1. 动态导入tiny-slider-react并禁用SSR

使用Next.js提供的dynamic函数,仅在客户端环境导入组件,避免服务端执行相关代码:

2. 优化状态初始化与依赖项

  • 直接在useState中判断window是否存在,减少一次无意义的渲染
  • 移除useEffect依赖中的window和setMount(setMount是稳定函数,无需加入依赖,window是全局变量,加入依赖会导致无限循环)

修改后的完整代码

"use client";
import CarouselItem from "./carousel-item";
import "tiny-slider/dist/tiny-slider.css";
import { useEffect, useState } from "react";
import dynamic from 'next/dynamic';

// 动态导入TinySlider,禁用SSR
const TinySlider = dynamic(() => import('tiny-slider-react'), {
  ssr: false,
  loading: () => null // 加载时显示null,也可以自定义加载组件
});

function Carousel(props) {
  // 直接初始化mount状态,判断window是否存在
  const [mount, setMount] = useState(typeof window !== 'undefined');

  useEffect(() => {
    // 确保客户端挂载后更新状态(可选,保险措施)
    setMount(true);
  }, []);

  const settings = {
    lazyload: true,
    nav: false,
    mouseDrag: true,
    loop: true,
    items: 1,
    gutter: 20,
    controls: false,
    autoplay: true,
    autoplayHoverPause: true,
    autoplayButtonOutput: false,
    speed: 250,
    autoplayTimeout: 2500,
    responsive: {
      2048: {
        items: 10,
      },
      1920: {
        items: 4,
      },
      1728: {
        items: 4,
      },
      1440: {
        items: 4,
      },
      1280: {
        items: 4,
      },
      1194: {
        items: 4,
      },
      1114: {
        items: 4,
      },
      1180: {
        items: 4,
      },
      1104: {
        items: 4,
      },
      1024: {
        items: 4,
      },
      834: {
        items: 2,
      },
      820: {
        items: 2,
      },
      800: {
        items: 2,
      },
      768: {
        items: 2,
      },
    },
  };

  if (mount) {
    return (
      <TinySlider settings={settings} onInit={() => {}}>
        {props.data.map((item) => (
          <CarouselItem key={item.id} data={item} />
        ))}
      </TinySlider>
    );
  }
  return null;
}

export default Carousel;

额外说明

  • 样式导入"tiny-slider/dist/tiny-slider.css"可以保留静态导入,因为样式文件不会执行JS逻辑,不会触发window错误
  • 如果自定义加载组件,可以替换loading: () => null为你需要的加载UI,比如一个骨架屏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:22:41