【问题标题】:React Hook who refer to DOM element return "null" on first call引用 DOM 元素的 React Hook 在第一次调用时返回“null”
【发布时间】:2019-10-05 12:32:37
【问题描述】:

我有一个钩子,可以捕获 ref DOM 元素的 getBoundingClientRect 对象。问题是,在第一次渲染时,它返回null,我只需要在组件的第一次渲染时获取值。

我在功能组件中使用它:

const App = () => {

  // create ref 
  const rootRef = useRef(null);

  // get Client Rect of rootRef 
  const refRect = useBoundingClientRect(rootRef);

  useEffect(()=> {
    // return "null" the first time
    // return "DOMRect" when refRect is update
    console.log(refRect)
  }, [refRect])

  return <div ref={rootRef} >App</div>

}

这里是useBoundingClientRect钩子,我调用了App Component。

export function useBoundingClientRect(pRef) {

  const getBoundingClientRect = useCallback(() => {
    return pRef && pRef.current && pRef.current.getBoundingClientRect();
  }, [pRef]);

  const [rect, setRect] = useState(null);

  useEffect(() => {
    setRect(getBoundingClientRect());
  },[]);

  return rect;
}

问题是我想在初始化时缓存 boundingClientRect 对象,而不是第二次重新渲染组件:

  // App Component

  useEffect(()=> {
    // I would like to get boundingClientRect the 1st time useEffect is call.
    console.log(refRect)

  // empty array allow to not re-execute the code in this useEffect
  }, [])

我检查了一些教程和文档,发现有些人使用useRef 而不是useState 挂钩来保持价值。所以我尝试在我的 useboundingClientRect 钩子中使用它来捕获并返回我的 App 组件第一次渲染时的 boundingClientRect 值。它可以工作......部分:

export function useBoundingClientRect(pRef) {

  const getBoundingClientRect = useCallback(() => {
    return pRef && pRef.current && pRef.current.getBoundingClientRect();
  }, [pRef]);

  const [rect, setRect] = useState(null);

  // create a new ref
  const rectRef = useRef(null)

  useEffect(() => {
    setRect(getBoundingClientRect());

    // set value in ref
    const rectRef = getBoundingClientRect()

  },[]);

  //  return rectRef for the first time 
  return rect === null ? rectRef : rect;
}

现在 App 组件中的 console.log(rectRef) 允许在第一次渲染时访问该值:

   // App Component

  useEffect(()=> {
    console.log(refRect.current)
  }, [])

但如果我尝试从useBoundingClientRect 返回refRect.current,则挂钩返回null。 (什么?!)

如果有人可以向我解释这些错误。提前致谢!

【问题讨论】:

  • const rectRef = 没有设置任何东西。它创建另一个局部变量。 rectRef.value = 就是你要找的...

标签: javascript reactjs react-hooks


【解决方案1】:

您需要在此处了解引用、变异和更新的异步性质。

首先,当您在useEffect 中运行自定义挂钩时,当您使用状态存储clientRect 属性时,它会在状态中设置值,该值将反映在下一个渲染周期中,因为状态更新是异步的。这就是为什么在第一次渲染时你会看到undefined

其次,当您返回rectRef 时,您实际上是在返回一个对象,当useBoundingClientRect 中的useEffect 运行时,您会在其中发生变异。在运行 useEffect 之前返回数据,因为它在渲染周期之后运行。现在,当组件内的useEffect 运行时,即在自定义挂钩内的useEffect 运行之后,数据已经存在并且已在其引用处由先前的useEffect 更新,因此您会看到正确的数据。

最后,如果您返回 rectRef.current,它现在是一个不可变值,自定义挂钩会更新该值,但由于前一个引用是 null,因此您看不到组件的变化@ 987654333@方法。

【讨论】:

  • 谢谢!对于返回rectRef.current的自定义钩子,我更好地理解了最后一部分发生的事情。您有什么建议可以实现这一目标吗?如果我尝试在 App 组件的 useEffect 中获取我的 ref 上的 getBoundingRectClient,我可以立即访问它,但如果我将自定义钩子中的逻辑外部化则不能。
猜你喜欢
  • 2021-04-09
  • 1970-01-01
  • 2020-06-21
  • 2018-09-20
  • 2023-03-28
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多