将useRef钩子传递给ref属性的正确方法

时间:2019-12-23 02:23:58

标签: reactjs react-hooks

我不确定如何用较模糊的方式表述问题,但这是关于按值传递按引用传递的案例。还有钩子。

我正在使用gsap为div滑入动画,这是上下文的上下文,但是我猜想ref所用的对象无关紧要。


所以,即使我理解这是通过ref传递类的更典型的组件方式,这种方法也能正常工作

const RootNavigation = () => {
var navbar = useRef();

const myTween = new TimelineLite({ paused: true });    
const animate = () => {
    myTween.to(navbar, 0.07, { x: "100" }).play();
  };

return(
     <div className="nav-main" ref={div => (navbar = div)}>   // <<<<<<<<<<   pass as a callback
     ...
    </div>
    )}

这会引发“ TypeError:无法添加属性_gsap,对象不可扩展”错误,即使这是React Hooks指南让我这样做的方式:

const RootNavigation = () => {
var navbar = useRef();

const myTween = new TimelineLite({ paused: true });    
const animate = () => {
    myTween.to(navbar, 0.07, { x: "100" }).play();
  };

return(
     <div className="nav-main" ref={navbar}>          //<<<<<<<<<<<<<  not passing a callback
     ...
    </div>
    )}

有人可以向我解释这里发生了什么,甚至扔一个男孩到已经解释过的地方的链接吗?我确定某种形式的Dan字符已在某处写过,但我不确定该如何使用Google。谢谢!

1 个答案:

答案 0 :(得分:2)

在第一个示例中,您没有使用ref,而是通过navbar回调重新分配ref,因此navbar是DOM元素。

相同
let navbar = null;

return <div ref={node => (navbar = node)} />

在第二个示例中,您使用的ref 对象是具有current属性的对象,该属性包含DOM元素

const navbar = useRef(null)

return <div ref={navbar} />

导航栏现在为

{ current: the DOM element }

因此,您要将对象传递到myTween.to()而不是navbar.current内的DOM元素

现在在第二个示例gsap中,尝试扩展ref对象本身而不是DOM元素。

为什么会出现TypeError:无法添加属性_gsap,对象不可扩展?

如果您查看useRef的源代码,则会在第891行看到

if (__DEV__) {
  Object.seal(ref);
}

React正在密封ref对象,而当我们尝试使用JavaScript扩展对象时,Object.defineProperty()会抛出错误,这很可能是gsap在做的事情。

使用ref的解决方案是将ref.current传递到tween.to()

const RootNavigation = () => {
  const navbar = useRef()

  const myTween = new TimelineLite({ paused: true });   

  const animate = () => {
    myTween.to(navbar.current, 0.07, { x: "100" }).play()
  }

  return (
    <div className="nav-main" ref={navbar}>
      ...
    </div>
  )
}