javascript 如何在useMemo中使用element ref?

csga3l58  于 2023-03-21  发布在  Java
关注(0)|答案(1)|浏览(108)

我有一个HTML元素nav,其中有一个ref设置,sideNavRef
我还想获取一个变量来控制该元素的动画,为此,我这样做:

const sideNavAnimation = useMemo(() => {
    if (sideNavRef.current) {
      const animations = createSideNavKeyframes({
        startingWidth: (7 * document.body.offsetWidth) / 100,
        endingWidth: 55,
      });
      const animation = sideNavRef.current.animate(animations.animation);
      animation.pause();
      return animation;
    }
  }, []);

createSideNavKeyframes返回一个关键帧数组,其中包含为每个步长计算的缓动值(0.1到1)。
缓动功能如下:

function easeInOutQuart(x: number): number {
  return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;
}

因为它需要计算这对每一个渲染我选择使用记忆值,因为它不会改变。
但是由于dependecy数组是空的,这意味着在第一次渲染中,ref的值仍然是未定义的,因此动画也是未定义的。
有没有更好的办法来解决这个问题?

nbysray5

nbysray51#

您的函数注册到sideNavRef.current,但尚未定义,因为useMemo在组件呈现之前运行。您可以在依赖数组中添加sideNavRef.current,以要求useMemo创建新版本的函数,但为此,您的组件应该以某种方式重新呈现,因为sideNavRef.current的改变不会触发re-render,而useMemo只会在渲染时检查它的依赖性。
例如,您可以使用名为componentRendred的状态,将其添加到依赖数组中,并在useEffect中更改其值,如下所示:

const [componentRendred, setComponentRendred] = useState(false);
const sideNavAnimation = useMemo(() => {
    if (sideNavRef.current) {
      const animations = createSideNavKeyframes({
        startingWidth: (7 * document.body.offsetWidth) / 100,
        endingWidth: 55,
      });
      const animation = sideNavRef.current.animate(animations.animation);
      animation.pause();
      return animation;
    }
  }, [componentRendred]);
useEffect(()=>{
  setComponentRendred(true);
},[])

相关问题