-
-
Notifications
You must be signed in to change notification settings - Fork 314
/
useRect.js
52 lines (43 loc) · 1.15 KB
/
useRect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import React from 'react'
import observeRect from '@reach/observe-rect'
import useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect'
export default function useRect(
nodeRef,
initialRect = { width: 0, height: 0 }
) {
const [element, setElement] = React.useState(nodeRef.current)
const [rect, dispatch] = React.useReducer(rectReducer, initialRect)
const initialRectSet = React.useRef(false)
useIsomorphicLayoutEffect(() => {
if (nodeRef.current !== element) {
setElement(nodeRef.current)
}
})
useIsomorphicLayoutEffect(() => {
if (element && !initialRectSet.current) {
initialRectSet.current = true
const rect = element.getBoundingClientRect()
dispatch({ rect })
}
}, [element])
React.useEffect(() => {
if (!element) {
return
}
const observer = observeRect(element, rect => {
dispatch({ rect })
})
observer.observe()
return () => {
observer.unobserve()
}
}, [element])
return rect
}
function rectReducer(state, action) {
const rect = action.rect
if (state.height !== rect.height || state.width !== rect.width) {
return rect
}
return state
}