在按钮单击中触发requestanimation reactjs钩子

时间:2019-01-27 07:58:16

标签: reactjs

我有这个钩子用来抽象SELECT * FROM (SELECT t1.*, Row_number() OVER( partition BY t1.alerttype, t1.alerttypeid, t1.macid ORDER BY t1.timestamp DESC) rn FROM alert_details LEFT JOIN alert_details_status t2 ON macid = c.macid AND t1.alerttypeid = t2.alerttypeid AND t1.alerttype = t2.alerttype AND t2.is_notified = true AND t2.escalation_status = 'completed' WHERE t2.alerttypeid IS NULL) t WHERE t.rn = 1

requestAnimationFrame

它的用法如下:

export const useAnimationIncrease = ({
  easingName = EasingName.linear,
  diff: end,
  duration = 500
}: AnimationIncreaseProps) => {
  const [increase, setIncrease] = useState(0);
  const start = useRef<any>(null);

  useLayoutEffect(() => {
    let raf: number;

    const frame = (timestamp: number) => {
      if (!start.current) {
        start.current = timestamp;
      }

      const time = timestamp - start.current;

      // get percent of completion in range [0, 1]
      const percentRange = Math.min(time / duration, 1);

      const percent = easing[easingName as string](percentRange);

      setIncrease(increase + end * percent);

      if (time < duration) {
        raf = requestAnimationFrame(frame);
      }
    };

    raf = requestAnimationFrame(frame);

    return () => {
      cancelAnimationFrame(raf);
    };
  },              [end]);

  return increase;
};

每次都会返回增加的值,因此我可以将其用于滚动等。

我该如何在单击按钮时触发此操作?或者我正在解决此错误。

如果我尝试这个;

const increase = useAnimationIncrease({ easingName: EasingName.inOutCubic, diff: 10 });

然后我收到错误消息:

  

只能在函数组件的主体内部调用钩子。

1 个答案:

答案 0 :(得分:4)

根据钩子规则

  

仅位于顶层的呼叫挂钩

     

请勿在循环,条件或嵌套函数中调用Hook。   相反,请始终在您的React函数的顶层使用挂钩。通过   遵循此规则,请确保在相同的位置调用钩子   每次渲染组件时订购。这就是让React能够   正确保留多个useState与之间的Hooks状态   useEffect调用。 (如果您有好奇心,我们将对此进行详细说明   

由于您通过在onClick事件处理程序中调用钩子违反了该规则,因此您将收到此警告

作为解决方法,您可以设置一个变量来触发动画

export const useAnimationIncrease = ({
  easingName = EasingName.linear,
  diff: end,
  duration = 500
}: AnimationIncreaseProps) => {
  const [increase, setIncrease] = useState(0);
  const [startAnimation, setStartAnimation] = useState(0);
  const start = useRef<any>(null);

  useLayoutEffect(() => {
    let raf: number;

    const frame = (timestamp: number) => {
      if (!start.current) {
        start.current = timestamp;
      }

      const time = timestamp - start.current;

      // get percent of completion in range [0, 1]
      const percentRange = Math.min(time / duration, 1);

      const percent = easing[easingName as string](percentRange);

      setIncrease(increase + end * percent);

      if (time < duration) {
        raf = requestAnimationFrame(frame);
      }
    };

    raf = requestAnimationFrame(frame);

    return () => {
      cancelAnimationFrame(raf);
    };
  },[end, startAnimation]);

  return [increase, startAnimation, setStartAnimation];
};

并像使用它

const [increase, startAnimation, setStartAnimation] = useAnimationIncrease({ easingName: EasingName.inOutCubic, diff: 10 });

onClick={(e) => {
   setStartAnimation(prev => prev + 1);
   // use increase now
}