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

如何在onClick事件中使用Web Animations API?解决React Hook调用错误

解决React Hook调用错误并实现狗狗点击跳跃动画

嘿,我来帮你搞定这个问题!你遇到的Invalid hook call错误是React的核心规则导致的——Hooks只能在函数组件的顶层作用域调用,绝对不能放在事件处理函数、循环或者条件判断里。你的useWebAnimations是在点击事件的回调DogJump里调用的,这就违反了规则,所以才会报错。

咱们来一步步修正代码,同时实现点击狗狗触发跳跃动画的效果:

修正后的完整代码

import React from "react";
import useWebAnimations from "@wellyshen/use-web-animations";
import "./App.css";
import Dog from "./images/dog.gif";
import Ball from "./images/ball.gif";

function App() {
  // 1. 在组件顶层调用useWebAnimations,符合Hook规则
  const { ref: dogRef, play, getAnimation } = useWebAnimations({
    // 定义跳跃动画的关键帧:原地→跳起来→回到原地
    keyframes: [
      { transform: "translate(0, 0)" },
      { transform: "translate(200px, -60px)" },
      { transform: "translate(0, 0)" }
    ],
    timing: {
      duration: 1200, // 动画时长1.2秒,更自然
      easing: "ease-in-out", // 缓动效果,模拟真实跳跃
      autoplay: false // 初始不自动播放,点击后再触发
    }
  });

  const handleDogJump = () => {
    // 2. 点击时重置并播放动画,避免多次点击导致动画混乱
    const animation = getAnimation();
    if (animation) {
      animation.cancel(); // 先取消当前正在运行的动画
      play(); // 重新播放跳跃动画
    }
  };

  return (
    <div>
      <img className="ball" src={Ball} alt="ball" />
      {/* 3. 用Hook返回的ref绑定狗狗图片,替代getElementById */}
      <img 
        ref={dogRef} 
        className="dog" 
        src={Dog} 
        alt="dog" 
        onClick={handleDogJump} 
      />
    </div>
  );
}

export default App;

关键改动说明

  • Hook调用位置修正:把useWebAnimations移到了组件的顶层作用域,完全符合React Hook的调用规则,解决了报错问题。
  • React Ref替代DOM查询:用Hook返回的dogRef绑定到img元素,这是React官方推荐的DOM操作方式,比getElementById更安全、更符合React的数据流。
  • 动画触发逻辑优化:关闭了autoplay,确保页面加载时动画不会自动播放;点击时先取消当前动画再重新播放,避免多次点击导致动画叠加混乱。
  • 动画效果优化:调整了关键帧的y轴偏移,让动画更像真实的跳跃,同时增加了缓动效果,提升视觉体验。

如果需要调整动画的时长、跳跃高度或者重复次数,直接修改timing配置里的参数就可以啦,比如添加iterations: 2让动画重复两次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:27:57