Redux 状态未在 requestAnimationFrame 中更新

Redux state not updating in requestAnimationFrame

更新 Redux 状态时,更新后的状态会在组件中接收,但不会在 requestAnimationFrame 函数中接收。

即我们可以注销组件声明顶部附近的更新状态 (backgroundMode) - 更新按预期记录:

const VideoCanvas = ({ videoRef }: IVideoCanvasProps) => {
  ...
  console.log("backgroundMode", backgroundMode);
  ...

但是在requestAnimationFrame函数中,每帧只注销初始值(None)

  async function animate() {
    ...

    // Does not receive updates from Redux store
    console.log("animate backgroundMode", backgroundMode);
    
    ...

    animationFrame.current = requestAnimationFrame(animate);

控制台输出如下所示:

backgroundMode None
(20) VideoCanvas.tsx:71 animate backgroundMode None

// change dropdown to blur mode
VideoCanvas.tsx:26 backgroundMode Blur
(23) VideoCanvas.tsx:71 animate backgroundMode None

// change dropdown to mask mode
VideoCanvas.tsx:26 backgroundMode Mask
(62) VideoCanvas.tsx:71 animate backgroundMode None

backgroundMode 添加到启动动画的 useEffect 的依赖项中,只会导致生成两个动画线程,从而使问题恶化。就目前而言,此效果如下所示:

  useEffect(() => {
    animationFrame.current = requestAnimationFrame(animate);
    return () => {
      if (animationFrame.current) {
        cancelAnimationFrame(animationFrame.current);
      }
    };
  }, [bodyPixNet]);

有问题的文件可以在我的 GitHub here

上完整查看

如有任何建议,我们将不胜感激!

这听起来像是 animate 函数中发生的旧的“陈旧状态封闭”问题。由于您正在递归调用 requestAnimationFrame 并从动画开始的渲染周期传递 animate 的值,因此您可能希望也在 ref 中缓存 backgroundMode 的副本,以便它可以随时更新,也可以随时读取当前值。使用 useEffect 挂钩更新缓存。

const backgroundModeRef = React.useRef(backgroundMode);

React.useEffect(() => {
  backgroundModeRef.current = backgroundMode;
}, [backgroundMode]);

animate函数中,引用缓存的ref值。

async function animate() {
  ...

  // Does not receive updates from Redux store
  console.log("animate backgroundMode", backgroundModeRef.current);

  ...

  animationFrame.current = requestAnimationFrame(animate);