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

Next.js结合Framer Motion使用window.innerWidth < 768报window未定义错求助

问题排查与修复方案

存在的问题

  • 服务端渲染兼容性错误:Next.js 会在服务端预先渲染组件HTML,Node.js 环境不存在 window 全局对象,你直接在组件顶层同步执行 window.innerWidth 会触发 ReferenceError: window is not defined 报错。
  • 变量声明错误:你使用 const 声明了 MobileView 变量,后续又对它重新赋值,const 声明的常量不允许重新赋值,会触发语法报错。
  • 缺少窗口变化监听:当前逻辑仅会在组件初始化时判断一次设备宽度,用户切换横竖屏、手动缩放窗口时,动画规则不会同步更新。

可运行修复示例

import React, { useEffect, useState } from "react";
import { useInView } from "react-intersection-observer";
import { motion, useAnimation } from "framer-motion";

export default function ValuesSection() {
  const controls = useAnimation();
  const [ref, inView] = useInView();
  // 初始化状态,服务端渲染阶段用默认值,避免访问window
  const [isMobile, setIsMobile] = useState(false);

  useEffect(() => {
    // 定义判断移动设备的方法
    const checkIsMobile = () => {
      setIsMobile(window.innerWidth < 768);
    };
    // 组件挂载到客户端后首次执行判断
    checkIsMobile();
    // 监听窗口大小变化,实时更新判断结果
    window.addEventListener('resize', checkIsMobile);
    // 组件卸载时清理事件监听,避免内存泄漏
    return () => window.removeEventListener('resize', checkIsMobile);
  }, []);

  // 根据设备类型动态返回动画配置
  const motionVariants = isMobile ? {} : {
    visible: { y: 0, scale: 1 },
    hidden: { y: 250, scale: 0 },
  };

  useEffect(() => {
    if (inView) {
      controls.start("visible");
    }
  }, [controls, inView]);

  return (
    <motion.div
      ref={ref}
      animate={controls}
      initial="hidden"
      variants={motionVariants}
    >
      Some content
    </motion.div>
  )
}

补充说明

如果不需要响应窗口变化,仅需要初始化时判断一次设备类型,可以去掉resize事件监听逻辑,仅在useEffect中执行一次宽度判断即可。

内容的提问来源于stack exchange,提问作者Mathias Riis Sorensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 15:30:04