从自定义钩子内部访问更改的状态变量(ReactJS)

时间:2021-03-17 14:46:07

标签: reactjs react-hooks

我有一个自定义的 useAnimationFrame 钩子:

import React, { useRef } from 'react';

const useAnimationFrame = (callback: (arg0: number) => void) => {
  // Use useRef for mutable variables that we want to persist
  // without triggering a re-render on their change
  const requestRef = useRef<number>();
  const previousTimeRef = useRef<number>();

  const animate = (time: number) => {
    if (previousTimeRef.current) {
      const deltaTime = time - previousTimeRef.current;
      callback(deltaTime);
    }
    previousTimeRef.current = time;
    requestRef.current = requestAnimationFrame(animate);
  };

  React.useEffect(() => {
    requestRef.current = requestAnimationFrame(animate);
    return () => {
      if (requestRef.current) {
        cancelAnimationFrame(requestRef.current);
      }
    };
  }, []); // Make sure the effect runs only once
};

export default useAnimationFrame;

我想用这种方式来更新每一帧发生的事情:

const exerciseRunning = useRef(true);
const directionForward = useRef(true);

const [progress, setProgress] = useState(0);

const [coord1, setCoord1] = useState({x: 0, y: 0});
const [coord2, setCoord2] = useState({x: 0, y: 0});

const [percentage, setPercentage] = useState(1);

useAnimationFrame((deltaTime) => {
    // Works!
    if (!exerciseRunning.current) {
      return;
    }

    // setProgress works!
    // directon.Forward works!
    // percentage does not work!
    setProgress((prevState) =>
      directionForward.current
        ? prevState + percentage * 1
        : prevState - percentage * 2
    );
  });

引用 exerciseRunningdirectionForward 都可以正常工作,setProgress 也是如此。

我知道,matching()percentage 部分是在第一次渲染时设置的(用于 useAnimationFrame 内部),之后不会更改。我需要如何更改构造,以便可以使用更新后的状态变量?

2 个答案:

答案 0 :(得分:0)

如果我理解正确,您是说matching() 不起作用,因为它总是返回false?如果是这样,您的问题不是参考而是函数本身。 您正在尝试用 === 比较两个不同的 对象,这将始终返回 false,因为对象将通过引用进行比较。所以你需要做一个深入的比较:

const matching = () => coord1.x === coord2.x && coord1.y === coord2.y;

答案 1 :(得分:0)

好的,所以我的解决方案很简单。所以对于任何有兴趣的人。我刚刚添加了将属性包含到我的自定义挂钩的选项。所以这是自定义钩子:

com.fasterxml.jackson.databind.ObjectMapper#readerForUpdating

以及功能组件内部的代码:

import React, { useRef } from 'react';

// ADDED DependencyList

const useAnimationFrame = (callback: (arg0: number) => void, deps?: DependencyList) => {
  // Use useRef for mutable variables that we want to persist
  // without triggering a re-render on their change
  const requestRef = useRef<number>();
  const previousTimeRef = useRef<number>();

  const animate = (time: number) => {
    if (previousTimeRef.current) {
      const deltaTime = time - previousTimeRef.current;
      callback(deltaTime);
    }
    previousTimeRef.current = time;
    requestRef.current = requestAnimationFrame(animate);
  };

  React.useEffect(() => {
    requestRef.current = requestAnimationFrame(animate);
    return () => {
      if (requestRef.current) {
        cancelAnimationFrame(requestRef.current);
      }
    };
  }, [deps]); // <--- HERE!!!
};

export default useAnimationFrame;