Skip to content

Commit 076d0de

Browse files
authored
feat: add useWindowScroll hook
2 parents 3e50e81 + 2fd08f8 commit 076d0de

File tree

5 files changed

+92
-0
lines changed

5 files changed

+92
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
- [`useNetwork`](./docs/useNetwork.md) — tracks state of user's internet connection.
4646
- [`useOrientation`](./docs/useOrientation.md) — tracks state of device's screen orientation.
4747
- [`useSize`](./docs/useSize.md) — tracks some HTML element's dimensions.
48+
- [`useWindowScroll`](./docs/useWindowScroll.md) — tracks `Window` scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usewindowscroll--docs)
4849
- [`useWindowSize`](./docs/useWindowSize.md) — tracks `Window` dimensions. [![][img-demo]](https://codesandbox.io/s/m7ln22668)
4950
<br/>
5051
<br/>

docs/useWindowScroll.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# `useWindowSize`
2+
3+
React sensor hook that re-renders on window scroll
4+
5+
## Usage
6+
7+
```jsx
8+
import {useWindowScroll} from 'react-use';
9+
10+
const Demo = () => {
11+
const {x, y} = useWindowScroll();
12+
13+
return (
14+
<div>
15+
<div>x: {x}</div>
16+
<div>y: {y}</div>
17+
</div>
18+
);
19+
};
20+
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as React from 'react';
2+
import {storiesOf} from '@storybook/react';
3+
import {useWindowScroll} from '..';
4+
import ShowDocs from '../util/ShowDocs';
5+
6+
const Demo = () => {
7+
const {x, y} = useWindowScroll();
8+
9+
return (
10+
<div style={{
11+
width: "200vw",
12+
height: "200vh"
13+
}}>
14+
<div style={{
15+
position: "fixed",
16+
left: 0,
17+
right: 0}}
18+
>
19+
<div>x: {x}</div>
20+
<div>y: {y}</div>
21+
</div>
22+
</div>
23+
);
24+
};
25+
26+
storiesOf('Sensors/useWindowScroll', module)
27+
.add('Docs', () => <ShowDocs md={require('../../docs/useWindowScroll.md')} />)
28+
.add('Demo', () =>
29+
<Demo/>
30+
)

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import useTween from './useTween';
4747
import useUnmount from './useUnmount';
4848
import useUpdate from './useUpdate';
4949
import useVideo from './useVideo';
50+
import useWindowScroll from './useWindowScroll';
5051
import useWindowSize from './useWindowSize';
5152
import useWait from './useWait';
5253
import useUpdateEffect from './useUpdateEffect'
@@ -101,6 +102,7 @@ export {
101102
useUnmount,
102103
useUpdate,
103104
useVideo,
105+
useWindowScroll,
104106
useWindowSize,
105107
useWait,
106108
useUpdateEffect

src/useWindowScroll.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {useState, useEffect, useRef} from 'react';
2+
import {isClient} from './util';
3+
4+
export interface State {
5+
x: number;
6+
y: number;
7+
}
8+
9+
const useWindowScroll = (): State => {
10+
const frame = useRef(0);
11+
const [state, setState] = useState<State>({
12+
x: isClient ? window.scrollX : 0,
13+
y: isClient ? window.scrollY : 0
14+
})
15+
16+
useEffect(() => {
17+
const handler = () => {
18+
cancelAnimationFrame(frame.current)
19+
20+
frame.current = requestAnimationFrame(() => {
21+
setState({
22+
x: window.scrollX,
23+
y: window.scrollY
24+
})
25+
})
26+
}
27+
28+
window.addEventListener('scroll', handler, {
29+
capture: false,
30+
passive: true
31+
})
32+
33+
return () => window.removeEventListener('scroll', handler)
34+
}, [])
35+
36+
return state
37+
}
38+
39+
export default useWindowScroll

0 commit comments

Comments
 (0)