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

使用TypeScript的Framer-motion动画:scrollY无法找到.current属性

解决useScroll钩子scrollY属性的类型定义问题

首先根据你的代码逻辑,明确scrollY的结构:它包含数值类型的current、prev属性,以及用于监听滚动变化的onChange方法。我们先定义对应的类型:

interface ScrollYState {
  current: number;
  prev: number;
  onChange: (callback: () => void) => () => void;
}

接下来根据useScroll的来源(自定义/第三方库),选择对应的类型处理方式:

方式一:为自定义useScroll钩子添加返回类型

如果useScroll是你自己实现的钩子,直接给它指定返回类型即可:

const useScroll = (): { scrollY: ScrollYState } => {
  // 这里是你的useScroll钩子实现逻辑
};

方式二:处理第三方库的useScroll类型缺失问题

如果是使用第三方库(比如react-use)的useScroll但类型不匹配,有两种快速解决方式:

类型断言(快速临时方案)

在解构时直接断言scrollY的类型:

const { scrollY } = useScroll() as { scrollY: ScrollYState };

模块扩展(优雅持久方案)

创建types/[库名].d.ts文件(比如types/react-use.d.ts),扩展原有模块的类型:

import 'react-use';

declare module 'react-use' {
  export function useScroll(): {
    scrollY: ScrollYState;
    // 可添加其他需要的属性,比如scrollX
  };
}

完整类型化后的业务代码

import { useState, useEffect } from 'react';

interface ScrollYState {
  current: number;
  prev: number;
  onChange: (callback: () => void) => () => void;
}

// 自定义useScroll示例(如果用第三方库可忽略这段)
const useScroll = (): { scrollY: ScrollYState } => {
  const [scrollState, setScrollState] = useState<ScrollYState>({
    current: 0,
    prev: 0,
    onChange: () => () => {},
  });

  useEffect(() => {
    const updateScroll = () => {
      setScrollState(prev => ({
        ...prev,
        prev: prev.current,
        current: window.scrollY,
      }));
    };

    window.addEventListener('scroll', updateScroll);
    const onChange = (callback: () => void) => {
      window.addEventListener('scroll', callback);
      return () => window.removeEventListener('scroll', callback);
    };

    return () => window.removeEventListener('scroll', updateScroll);
  }, []);

  return { scrollY: { ...scrollState, onChange } };
};

// 菜单组件代码
const ScrollMenu = () => {
  const { scrollY } = useScroll();
  const [isScrolling, setScrolling] = useState<boolean>(false);

  const handleScroll = () => {
    // 类型明确后可去掉可选链,让TypeScript做严格检查
    if (scrollY.current < scrollY.prev) setScrolling(false);
    if (scrollY.current > 100 && scrollY.current > scrollY.prev) setScrolling(true);
  };

  useEffect(() => {
    return scrollY.onChange(handleScroll);
  }, [scrollY]);

  return (
    <div className={`menu ${isScrolling ? 'hidden' : 'visible'}`}>
      {/* 菜单内容 */}
    </div>
  );
};

注意事项

  • 优先查看第三方库的官方文档,确认是否有现成的类型定义包(比如@types/[库名])
  • 类型定义要和scrollY的实际运行时结构完全匹配,避免类型不兼容报错

内容的提问来源于stack exchange,提问作者Adrián Pérez García

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:35:33