将 useRef 钩子传递给 ref 属性的正确方法 [英] Correct way to pass useRef hook to ref property

查看:27
本文介绍了将 useRef 钩子传递给 ref 属性的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何不那么模糊地表述这个问题,但它是关于 React 中传值传引用的情况.还有钩子.

我正在使用 gsap 为 div 滑入和滑出设置动画,这是上下文,但我猜想 ref 的用途应该无关紧要.><小时>

所以,这很好用,即使这是我理解的一种更典型的类组件传递引用的方式:

const RootNavigation = () =>{var navbar = useRef();const myTween = new TimelineLite({ paused: true });const animate = () =>{myTween.to(navbar, 0.07, { x: "100" }).play();};返回(<div className="nav-main" ref={div =>(导航栏 = div)}>//<<<<<<<<<<作为回调传递...

)}

这会引发类型错误:无法添加属性 _gsap,对象不可扩展"错误,尽管 React Hooks 指南希望我这样做:

const RootNavigation = () =>{var navbar = useRef();const myTween = new TimelineLite({ paused: true });const animate = () =>{myTween.to(navbar, 0.07, { x: "100" }).play();};返回(<div className="nav-main" ref={navbar}>//<<<<<<<<<<<<<不传递回调...

)}

有人可以向我解释这里发生了什么,或者甚至可以给一个男孩一个链接到已经解释过的地方吗?我确定某种丹角色已经在某处写过它,我只是不确定要谷歌什么.谢谢!

解决方案

在第一个示例中,您没有使用 ref,而是通过 navbar 重新分配 navbarcode>ref 回调所以 navbar 是 DOM 元素.

一样

let navbar = null;返回 

(导航栏 = 节点)}/>

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

const navbar = useRef(null)返回 <div ref={navbar}/>

导航栏现在是

{ current: DOM 元素 }

因此您将对象传递到 myTween.to() 而不是 navbar.current

中的 DOM 元素

现在在第二个例子中 gsap 试图扩展 ref 对象本身而不是 DOM 元素.

为什么我们会得到 TypeError: Cannot add property _gsap, object is not extensible`?

如果查看useRef 你会在 891

行看到

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

当我们尝试使用 Object.defineProperty() 扩展它时,React 正在密封 ref 对象并且 JavaScript 将抛出错误可能是 gsap 正在做的.

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

const RootNavigation = () =>{const 导航栏 = useRef()const myTween = new TimelineLite({ paused: true });const animate = () =>{myTween.to(navbar.current, 0.07, { x: "100" }).play()}返回 (<div className="nav-main" ref={navbar}>...

)}

I'm not sure how to formulate the question less vaguely, but it's about pass-by-value and pass-by-reference cases in react. And Hooks.

I am using gsap to animate a div slide-in and out is the context for this, but I'm going to guess that what the ref is used for shouldn't matter.


So, this works fine, even though this is a more class-component-typical way of passing a ref as i understand it:

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>
    )}

And this elicits a "TypeError: Cannot add property _gsap, object is not extensible" error, even though this is how the React Hooks guide would have me do it:

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>
    )}

Could somebody explain to me what's going on here or even toss a boy a link to where it's already been explained? I'm sure some sort of Dan character has written about it somewhere, i'm just not sure what to google. Thank you!

解决方案

In the first example you aren't using a ref, you are reassigning navbar through the ref callback so navbar is the DOM element.

It's the same as

let navbar = null;

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

In the second example you are using the ref object which is an object with a current property that holds the DOM element

const navbar = useRef(null)

return <div ref={navbar} />

navbar is now

{ current: the DOM element }

So you are passing the object into myTween.to() instead of the DOM element inside navbar.current

Now in the second example gsap is trying to extend the ref object itself and not the DOM element.

Why do we get the TypeError: Cannot add property _gsap, object is not extensible`?

If you look at the source code of useRef you will see on line 891

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

that React is sealing the ref object and JavaScript will throw an error when we try to extend it using Object.defineProperty() which is probably what gsap is doing.

The solution for using a ref will be to pass ref.current into 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>
  )
}

这篇关于将 useRef 钩子传递给 ref 属性的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆