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

React Hooks媒体查询问题:reduced-motion钩子中window对象未定义

解决React Hook中检测Reduced Motion时window未定义的问题

先看你代码里的几个核心问题:

  • windowRef 初始化后从未赋值,始终为null,强制访问windowRef.current!会直接抛出错误
  • 依赖数组里传入window没有意义,且在SSR(服务端渲染)场景下,window本身就不存在
  • matchMedia的查询字符串缺少闭合括号,属于语法错误

下面是修正后的完整Hook,同时补上了监听媒体查询动态变化的逻辑(用户可能在浏览器设置中修改动画偏好):

import { useEffect, useState } from "react";

/**
 * Checks if the browser is running on reduced motion
 * @returns true if the browser is running on reduced motion
 */
const usePrefersReducedMotion = (): boolean => {
  // SSR环境下初始值设为false,可根据实际需求调整
  const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);

  useEffect(() => {
    // 先判断是否处于浏览器环境
    if (typeof window === 'undefined') return;

    const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");

    // 定义状态更新函数
    const updateStatus = () => {
      setPrefersReducedMotion(mediaQuery.matches);
    };
    // 设置初始状态
    updateStatus();

    // 监听媒体查询变化
    mediaQuery.addEventListener('change', updateStatus);

    // 组件卸载时移除监听,避免内存泄漏
    return () => {
      mediaQuery.removeEventListener('change', updateStatus);
    };
  }, []); // 空依赖数组,仅在组件挂载时执行一次

  return prefersReducedMotion;
};

export default usePrefersReducedMotion;

关键说明:

  • 用typeof window === 'undefined'做环境判断,兼容Next.js、Gatsby等SSR/SSG场景
  • 直接在useEffect中使用window.matchMedia,客户端挂载阶段window已存在,无需额外ref存储
  • 添加change事件监听,确保用户修改浏览器动画设置时,状态能同步更新
  • 组件卸载时清理监听事件,避免潜在的内存泄漏问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:32:42