我有一个钩子,钩住了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钩子。
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;
}
问题是我想在init上缓存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;
}
现在,应用程序组件中的console.log(rectRef)
允许访问第一个渲染的值:
// App Component
useEffect(()=> {
console.log(refRect.current)
}, [])
但是,如果我尝试从refRect.current
钩返回useBoundingClientRect
,请返回null
。 (什么?!)
如果有人可以向我解释这些错误。预先感谢!
答案 0 :(得分:1)
您需要在此处了解更新的参考,变异和异步性质
首先,当您使用状态存储clientRect
属性时,当您运行自定义钩子useEffect
时,由于状态更新是异步的,因此它将状态设置为值,该值将反映在下一个渲染周期中。这就是为什么在第一次渲染时会看到未定义的原因。
第二,当您返回rectRef
时,实际上是在返回一个对象,该对象随后在useEffect
中的useBoundingClientRect
运行时发生变异。在渲染周期之后运行useEffect
之前,将返回数据。现在,当组件中的useEffect
(在自定义钩子中的useEffect之后)运行时,数据已经存在,并且已被先前的useEffect
对其进行了更新,因此您将看到正确的数据。 / p>
但是在这里,如果您返回rectRef.current
现在是一个不可变的值,则自定义钩子会更新该值,但是由于前一个是null
,因此该钩子将使用新的引用,因此您看不到更改在您的组件useEFfect
方法中。